diff --git a/src/irc/client.go b/src/irc/client.go index bcaa34b9..9394fd44 100644 --- a/src/irc/client.go +++ b/src/irc/client.go @@ -27,11 +27,6 @@ type Client struct { replies chan<- Reply } -type ClientMessage interface { - Client() *Client - SetClient(*Client) -} - type ClientSet map[*Client]bool func NewClient(server *Server, conn net.Conn) *Client { diff --git a/src/irc/commands.go b/src/irc/commands.go index 8fbf1b1f..a08b2ce8 100644 --- a/src/irc/commands.go +++ b/src/irc/commands.go @@ -14,17 +14,25 @@ type BaseCommand struct { client *Client } -func (base *BaseCommand) Client() *Client { +func (base BaseCommand) Client() *Client { return base.client } func (base *BaseCommand) SetClient(c *Client) { + if base.client != nil { + panic("SetClient called twice!") + } base.client = c } +type EditableCommand interface { + Command + SetClient(*Client) +} + var ( ErrParseCommand = errors.New("failed to parse message") - parseCommandFuncs = map[string]func([]string) (Command, error){ + parseCommandFuncs = map[string]func([]string) (EditableCommand, error){ "JOIN": NewJoinCommand, "MODE": NewModeCommand, "NICK": NewNickCommand, @@ -39,7 +47,7 @@ var ( } ) -func ParseCommand(line string) (Command, error) { +func ParseCommand(line string) (EditableCommand, error) { command, args := parseLine(line) constructor := parseCommandFuncs[command] if constructor == nil { @@ -77,14 +85,14 @@ func parseLine(line string) (command string, args []string) { // [args...] type UnknownCommand struct { - *BaseCommand + BaseCommand command string args []string } func NewUnknownCommand(command string, args []string) *UnknownCommand { return &UnknownCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, command: command, args: args, } @@ -93,17 +101,17 @@ func NewUnknownCommand(command string, args []string) *UnknownCommand { // PING [ ] type PingCommand struct { - *BaseCommand + BaseCommand server string server2 string } -func NewPingCommand(args []string) (Command, error) { +func NewPingCommand(args []string) (EditableCommand, error) { if len(args) < 1 { return nil, NotEnoughArgsError } msg := &PingCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, server: args[0], } if len(args) > 1 { @@ -115,17 +123,17 @@ func NewPingCommand(args []string) (Command, error) { // PONG [ ] type PongCommand struct { - *BaseCommand + BaseCommand server1 string server2 string } -func NewPongCommand(args []string) (Command, error) { +func NewPongCommand(args []string) (EditableCommand, error) { if len(args) < 1 { return nil, NotEnoughArgsError } message := &PongCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, server1: args[0], } if len(args) > 1 { @@ -137,16 +145,16 @@ func NewPongCommand(args []string) (Command, error) { // PASS type PassCommand struct { - *BaseCommand + BaseCommand password string } -func NewPassCommand(args []string) (Command, error) { +func NewPassCommand(args []string) (EditableCommand, error) { if len(args) < 1 { return nil, NotEnoughArgsError } return &PassCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, password: args[0], }, nil } @@ -154,16 +162,16 @@ func NewPassCommand(args []string) (Command, error) { // NICK type NickCommand struct { - *BaseCommand + BaseCommand nickname string } -func NewNickCommand(args []string) (Command, error) { +func NewNickCommand(args []string) (EditableCommand, error) { if len(args) != 1 { return nil, NotEnoughArgsError } return &NickCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, nickname: args[0], }, nil } @@ -171,19 +179,19 @@ func NewNickCommand(args []string) (Command, error) { // USER type UserMsgCommand struct { - *BaseCommand + BaseCommand user string mode uint8 unused string realname string } -func NewUserMsgCommand(args []string) (Command, error) { +func NewUserMsgCommand(args []string) (EditableCommand, error) { if len(args) != 4 { return nil, NotEnoughArgsError } msg := &UserMsgCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, user: args[0], unused: args[2], realname: args[3], @@ -198,13 +206,13 @@ func NewUserMsgCommand(args []string) (Command, error) { // QUIT [ ] type QuitCommand struct { - *BaseCommand + BaseCommand message string } -func NewQuitCommand(args []string) (Command, error) { +func NewQuitCommand(args []string) (EditableCommand, error) { msg := &QuitCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, } if len(args) > 0 { msg.message = args[0] @@ -215,14 +223,14 @@ func NewQuitCommand(args []string) (Command, error) { // JOIN ( *( "," ) [ *( "," ) ] ) / "0" type JoinCommand struct { - *BaseCommand + BaseCommand channels map[string]string zero bool } -func NewJoinCommand(args []string) (Command, error) { +func NewJoinCommand(args []string) (EditableCommand, error) { msg := &JoinCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, channels: make(map[string]string), } @@ -252,17 +260,17 @@ func NewJoinCommand(args []string) (Command, error) { // PART *( "," ) [ ] type PartCommand struct { - *BaseCommand + BaseCommand channels []string message string } -func NewPartCommand(args []string) (Command, error) { +func NewPartCommand(args []string) (EditableCommand, error) { if len(args) < 1 { return nil, NotEnoughArgsError } msg := &PartCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, channels: strings.Split(args[0], ","), } if len(args) > 1 { @@ -274,17 +282,17 @@ func NewPartCommand(args []string) (Command, error) { // PRIVMSG type PrivMsgCommand struct { - *BaseCommand + BaseCommand target string message string } -func NewPrivMsgCommand(args []string) (Command, error) { +func NewPrivMsgCommand(args []string) (EditableCommand, error) { if len(args) < 2 { return nil, NotEnoughArgsError } return &PrivMsgCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, target: args[0], message: args[1], }, nil @@ -301,17 +309,17 @@ func (m *PrivMsgCommand) TargetIsChannel() bool { // TOPIC [newtopic] type TopicCommand struct { - *BaseCommand + BaseCommand channel string topic string } -func NewTopicCommand(args []string) (Command, error) { +func NewTopicCommand(args []string) (EditableCommand, error) { if len(args) < 1 { return nil, NotEnoughArgsError } msg := &TopicCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, channel: args[0], } if len(args) > 1 { @@ -321,18 +329,18 @@ func NewTopicCommand(args []string) (Command, error) { } type ModeCommand struct { - *BaseCommand + BaseCommand nickname string modes string } -func NewModeCommand(args []string) (Command, error) { +func NewModeCommand(args []string) (EditableCommand, error) { if len(args) == 0 { return nil, NotEnoughArgsError } cmd := &ModeCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, nickname: args[0], } diff --git a/src/irc/nickserv.go b/src/irc/nickserv.go index ce5d44b7..c86bae75 100644 --- a/src/irc/nickserv.go +++ b/src/irc/nickserv.go @@ -5,8 +5,9 @@ import ( ) type NickServCommand interface { - ClientMessage HandleNickServ(*NickServ) + Client() *Client + SetClient(*Client) } type NickServ struct { @@ -14,11 +15,9 @@ type NickServ struct { } func NewNickServ(s *Server) *NickServ { - ns := &NickServ{} - ns.Service = NewService(s, "NickServ", func(m *PrivMsgCommand) { - m.HandleNickServ(ns) - }) - return ns + return &NickServ{ + Service: NewService(s, "NickServ"), + } } var ( @@ -32,7 +31,7 @@ var ( // commands // -func (m *PrivMsgCommand) HandleNickServ(ns *NickServ) { +func (ns *NickServ) HandleMsg(m *PrivMsgCommand) { command, args := parseLine(m.message) constructor := parseNickServCommandFuncs[command] if constructor == nil { @@ -48,6 +47,7 @@ func (m *PrivMsgCommand) HandleNickServ(ns *NickServ) { cmd.SetClient(m.Client()) log.Printf("%s %T %+v", ns.Id(), cmd, cmd) + cmd.HandleNickServ(ns) } @@ -56,7 +56,7 @@ func (m *PrivMsgCommand) HandleNickServ(ns *NickServ) { // type RegisterCommand struct { - *BaseCommand + BaseCommand password string email string } @@ -67,7 +67,7 @@ func NewRegisterCommand(args []string) (NickServCommand, error) { } cmd := &RegisterCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, password: args[0], } if len(args) > 1 { @@ -100,7 +100,7 @@ func (m *RegisterCommand) HandleNickServ(ns *NickServ) { } type IdentifyCommand struct { - *BaseCommand + BaseCommand password string } @@ -110,7 +110,7 @@ func NewIdentifyCommand(args []string) (NickServCommand, error) { } return &IdentifyCommand{ - BaseCommand: &BaseCommand{}, + BaseCommand: BaseCommand{}, password: args[0], }, nil } diff --git a/src/irc/server.go b/src/irc/server.go index ba7a51e5..63bff3cb 100644 --- a/src/irc/server.go +++ b/src/irc/server.go @@ -13,8 +13,8 @@ type UserNameMap map[string]*User type ServiceNameMap map[string]*Service type Command interface { - ClientMessage - Handle(*Server) + Client() *Client + HandleServer(*Server) } type Server struct { @@ -47,7 +47,7 @@ func (server *Server) receiveCommands(commands <-chan Command) { for command := range commands { log.Printf("%s %T %+v", server.Id(), command, command) command.Client().atime = time.Now() - command.Handle(server) + command.HandleServer(server) } } @@ -127,19 +127,19 @@ func (s *Server) DeleteChannel(channel *Channel) { // commands // -func (m *UnknownCommand) Handle(s *Server) { +func (m *UnknownCommand) HandleServer(s *Server) { m.Client().replies <- ErrUnknownCommand(s, m.command) } -func (m *PingCommand) Handle(s *Server) { +func (m *PingCommand) HandleServer(s *Server) { m.Client().replies <- RplPong(s) } -func (m *PongCommand) Handle(s *Server) { +func (m *PongCommand) HandleServer(s *Server) { // no-op } -func (m *PassCommand) Handle(s *Server) { +func (m *PassCommand) HandleServer(s *Server) { err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password)) if err != nil { m.Client().replies <- ErrPasswdMismatch(s) @@ -150,7 +150,7 @@ func (m *PassCommand) Handle(s *Server) { // no reply? } -func (m *NickCommand) Handle(s *Server) { +func (m *NickCommand) HandleServer(s *Server) { c := m.Client() if c.user == nil { c.replies <- RplNick(c, m.nickname) @@ -162,7 +162,7 @@ func (m *NickCommand) Handle(s *Server) { c.user.replies <- ErrNoPrivileges(s) } -func (m *UserMsgCommand) Handle(s *Server) { +func (m *UserMsgCommand) HandleServer(s *Server) { c := m.Client() if c.username != "" { c.replies <- ErrAlreadyRegistered(s) @@ -173,7 +173,7 @@ func (m *UserMsgCommand) Handle(s *Server) { s.tryRegister(c) } -func (m *QuitCommand) Handle(s *Server) { +func (m *QuitCommand) HandleServer(s *Server) { c := m.Client() user := c.user @@ -191,7 +191,7 @@ func (m *QuitCommand) Handle(s *Server) { user.LogoutClient(c) if !user.HasClients() { cmd := &PartCommand{ - BaseCommand: &BaseCommand{c}, + BaseCommand: BaseCommand{c}, } for channel := range user.channels { channel.commands <- cmd @@ -199,7 +199,7 @@ func (m *QuitCommand) Handle(s *Server) { } } -func (m *JoinCommand) Handle(s *Server) { +func (m *JoinCommand) HandleServer(s *Server) { c := m.Client() if c.user == nil { @@ -211,7 +211,7 @@ func (m *JoinCommand) Handle(s *Server) { if m.zero { cmd := &PartCommand{ - BaseCommand: &BaseCommand{c}, + BaseCommand: BaseCommand{c}, } for channel := range c.user.channels { channel.commands <- cmd @@ -224,7 +224,7 @@ func (m *JoinCommand) Handle(s *Server) { } } -func (m *PartCommand) Handle(s *Server) { +func (m *PartCommand) HandleServer(s *Server) { user := m.Client().user if user == nil { @@ -246,7 +246,7 @@ func (m *PartCommand) Handle(s *Server) { } } -func (m *TopicCommand) Handle(s *Server) { +func (m *TopicCommand) HandleServer(s *Server) { user := m.Client().user if user == nil { @@ -263,7 +263,7 @@ func (m *TopicCommand) Handle(s *Server) { channel.commands <- m } -func (m *PrivMsgCommand) Handle(s *Server) { +func (m *PrivMsgCommand) HandleServer(s *Server) { service := s.services[m.target] if service != nil { service.commands <- m @@ -296,6 +296,6 @@ func (m *PrivMsgCommand) Handle(s *Server) { target.commands <- m } -func (m *ModeCommand) Handle(s *Server) { +func (m *ModeCommand) HandleServer(s *Server) { m.Client().replies <- RplUModeIs(s, m.Client()) } diff --git a/src/irc/service.go b/src/irc/service.go index 4f3842ce..b1dba229 100644 --- a/src/irc/service.go +++ b/src/irc/service.go @@ -10,28 +10,27 @@ type ServiceCommand interface { HandleService(*Service) } -type PrivMsgCommandFunc func(*PrivMsgCommand) - type Service struct { server *Server name string commands chan<- ServiceCommand - Handle PrivMsgCommandFunc } -func NewService(s *Server, name string, Handle PrivMsgCommandFunc) *Service { +func NewService(s *Server, name string) *Service { commands := make(chan ServiceCommand) service := &Service{ server: s, name: name, commands: commands, - Handle: Handle, } go service.receiveCommands(commands) s.services[name] = service return service } +func (service *Service) HandleMsg(m *PrivMsgCommand) { +} + func (service *Service) receiveCommands(commands <-chan ServiceCommand) { for command := range commands { log.Printf("%s %T %+V", service.Id(), command, command) @@ -60,5 +59,5 @@ func (service *Service) Reply(client *Client, message string) { // func (m *PrivMsgCommand) HandleService(s *Service) { - s.Handle(m) + s.HandleMsg(m) }