3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-26 13:59:44 +01:00

Clean up BaseCommand interface. Make NickServ a Service.

This commit is contained in:
Jeremy Latt 2013-05-09 09:12:03 -07:00
parent 4b0cfa816c
commit 39f815df01
5 changed files with 79 additions and 77 deletions

View File

@ -27,11 +27,6 @@ type Client struct {
replies chan<- Reply replies chan<- Reply
} }
type ClientMessage interface {
Client() *Client
SetClient(*Client)
}
type ClientSet map[*Client]bool type ClientSet map[*Client]bool
func NewClient(server *Server, conn net.Conn) *Client { func NewClient(server *Server, conn net.Conn) *Client {

View File

@ -14,17 +14,25 @@ type BaseCommand struct {
client *Client client *Client
} }
func (base *BaseCommand) Client() *Client { func (base BaseCommand) Client() *Client {
return base.client return base.client
} }
func (base *BaseCommand) SetClient(c *Client) { func (base *BaseCommand) SetClient(c *Client) {
if base.client != nil {
panic("SetClient called twice!")
}
base.client = c base.client = c
} }
type EditableCommand interface {
Command
SetClient(*Client)
}
var ( var (
ErrParseCommand = errors.New("failed to parse message") ErrParseCommand = errors.New("failed to parse message")
parseCommandFuncs = map[string]func([]string) (Command, error){ parseCommandFuncs = map[string]func([]string) (EditableCommand, error){
"JOIN": NewJoinCommand, "JOIN": NewJoinCommand,
"MODE": NewModeCommand, "MODE": NewModeCommand,
"NICK": NewNickCommand, "NICK": NewNickCommand,
@ -39,7 +47,7 @@ var (
} }
) )
func ParseCommand(line string) (Command, error) { func ParseCommand(line string) (EditableCommand, error) {
command, args := parseLine(line) command, args := parseLine(line)
constructor := parseCommandFuncs[command] constructor := parseCommandFuncs[command]
if constructor == nil { if constructor == nil {
@ -77,14 +85,14 @@ func parseLine(line string) (command string, args []string) {
// <command> [args...] // <command> [args...]
type UnknownCommand struct { type UnknownCommand struct {
*BaseCommand BaseCommand
command string command string
args []string args []string
} }
func NewUnknownCommand(command string, args []string) *UnknownCommand { func NewUnknownCommand(command string, args []string) *UnknownCommand {
return &UnknownCommand{ return &UnknownCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
command: command, command: command,
args: args, args: args,
} }
@ -93,17 +101,17 @@ func NewUnknownCommand(command string, args []string) *UnknownCommand {
// PING <server1> [ <server2> ] // PING <server1> [ <server2> ]
type PingCommand struct { type PingCommand struct {
*BaseCommand BaseCommand
server string server string
server2 string server2 string
} }
func NewPingCommand(args []string) (Command, error) { func NewPingCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &PingCommand{ msg := &PingCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
server: args[0], server: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
@ -115,17 +123,17 @@ func NewPingCommand(args []string) (Command, error) {
// PONG <server> [ <server2> ] // PONG <server> [ <server2> ]
type PongCommand struct { type PongCommand struct {
*BaseCommand BaseCommand
server1 string server1 string
server2 string server2 string
} }
func NewPongCommand(args []string) (Command, error) { func NewPongCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
message := &PongCommand{ message := &PongCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
server1: args[0], server1: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
@ -137,16 +145,16 @@ func NewPongCommand(args []string) (Command, error) {
// PASS <password> // PASS <password>
type PassCommand struct { type PassCommand struct {
*BaseCommand BaseCommand
password string password string
} }
func NewPassCommand(args []string) (Command, error) { func NewPassCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
return &PassCommand{ return &PassCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
password: args[0], password: args[0],
}, nil }, nil
} }
@ -154,16 +162,16 @@ func NewPassCommand(args []string) (Command, error) {
// NICK <nickname> // NICK <nickname>
type NickCommand struct { type NickCommand struct {
*BaseCommand BaseCommand
nickname string nickname string
} }
func NewNickCommand(args []string) (Command, error) { func NewNickCommand(args []string) (EditableCommand, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
return &NickCommand{ return &NickCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
nickname: args[0], nickname: args[0],
}, nil }, nil
} }
@ -171,19 +179,19 @@ func NewNickCommand(args []string) (Command, error) {
// USER <user> <mode> <unused> <realname> // USER <user> <mode> <unused> <realname>
type UserMsgCommand struct { type UserMsgCommand struct {
*BaseCommand BaseCommand
user string user string
mode uint8 mode uint8
unused string unused string
realname string realname string
} }
func NewUserMsgCommand(args []string) (Command, error) { func NewUserMsgCommand(args []string) (EditableCommand, error) {
if len(args) != 4 { if len(args) != 4 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &UserMsgCommand{ msg := &UserMsgCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
user: args[0], user: args[0],
unused: args[2], unused: args[2],
realname: args[3], realname: args[3],
@ -198,13 +206,13 @@ func NewUserMsgCommand(args []string) (Command, error) {
// QUIT [ <Quit Command> ] // QUIT [ <Quit Command> ]
type QuitCommand struct { type QuitCommand struct {
*BaseCommand BaseCommand
message string message string
} }
func NewQuitCommand(args []string) (Command, error) { func NewQuitCommand(args []string) (EditableCommand, error) {
msg := &QuitCommand{ msg := &QuitCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
} }
if len(args) > 0 { if len(args) > 0 {
msg.message = args[0] msg.message = args[0]
@ -215,14 +223,14 @@ func NewQuitCommand(args []string) (Command, error) {
// JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0" // JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"
type JoinCommand struct { type JoinCommand struct {
*BaseCommand BaseCommand
channels map[string]string channels map[string]string
zero bool zero bool
} }
func NewJoinCommand(args []string) (Command, error) { func NewJoinCommand(args []string) (EditableCommand, error) {
msg := &JoinCommand{ msg := &JoinCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
channels: make(map[string]string), channels: make(map[string]string),
} }
@ -252,17 +260,17 @@ func NewJoinCommand(args []string) (Command, error) {
// PART <channel> *( "," <channel> ) [ <Part Command> ] // PART <channel> *( "," <channel> ) [ <Part Command> ]
type PartCommand struct { type PartCommand struct {
*BaseCommand BaseCommand
channels []string channels []string
message string message string
} }
func NewPartCommand(args []string) (Command, error) { func NewPartCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &PartCommand{ msg := &PartCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
channels: strings.Split(args[0], ","), channels: strings.Split(args[0], ","),
} }
if len(args) > 1 { if len(args) > 1 {
@ -274,17 +282,17 @@ func NewPartCommand(args []string) (Command, error) {
// PRIVMSG <target> <message> // PRIVMSG <target> <message>
type PrivMsgCommand struct { type PrivMsgCommand struct {
*BaseCommand BaseCommand
target string target string
message string message string
} }
func NewPrivMsgCommand(args []string) (Command, error) { func NewPrivMsgCommand(args []string) (EditableCommand, error) {
if len(args) < 2 { if len(args) < 2 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
return &PrivMsgCommand{ return &PrivMsgCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
target: args[0], target: args[0],
message: args[1], message: args[1],
}, nil }, nil
@ -301,17 +309,17 @@ func (m *PrivMsgCommand) TargetIsChannel() bool {
// TOPIC [newtopic] // TOPIC [newtopic]
type TopicCommand struct { type TopicCommand struct {
*BaseCommand BaseCommand
channel string channel string
topic string topic string
} }
func NewTopicCommand(args []string) (Command, error) { func NewTopicCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &TopicCommand{ msg := &TopicCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
channel: args[0], channel: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
@ -321,18 +329,18 @@ func NewTopicCommand(args []string) (Command, error) {
} }
type ModeCommand struct { type ModeCommand struct {
*BaseCommand BaseCommand
nickname string nickname string
modes string modes string
} }
func NewModeCommand(args []string) (Command, error) { func NewModeCommand(args []string) (EditableCommand, error) {
if len(args) == 0 { if len(args) == 0 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
cmd := &ModeCommand{ cmd := &ModeCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
nickname: args[0], nickname: args[0],
} }

View File

@ -5,8 +5,9 @@ import (
) )
type NickServCommand interface { type NickServCommand interface {
ClientMessage
HandleNickServ(*NickServ) HandleNickServ(*NickServ)
Client() *Client
SetClient(*Client)
} }
type NickServ struct { type NickServ struct {
@ -14,11 +15,9 @@ type NickServ struct {
} }
func NewNickServ(s *Server) *NickServ { func NewNickServ(s *Server) *NickServ {
ns := &NickServ{} return &NickServ{
ns.Service = NewService(s, "NickServ", func(m *PrivMsgCommand) { Service: NewService(s, "NickServ"),
m.HandleNickServ(ns) }
})
return ns
} }
var ( var (
@ -32,7 +31,7 @@ var (
// commands // commands
// //
func (m *PrivMsgCommand) HandleNickServ(ns *NickServ) { func (ns *NickServ) HandleMsg(m *PrivMsgCommand) {
command, args := parseLine(m.message) command, args := parseLine(m.message)
constructor := parseNickServCommandFuncs[command] constructor := parseNickServCommandFuncs[command]
if constructor == nil { if constructor == nil {
@ -48,6 +47,7 @@ func (m *PrivMsgCommand) HandleNickServ(ns *NickServ) {
cmd.SetClient(m.Client()) cmd.SetClient(m.Client())
log.Printf("%s %T %+v", ns.Id(), cmd, cmd) log.Printf("%s %T %+v", ns.Id(), cmd, cmd)
cmd.HandleNickServ(ns) cmd.HandleNickServ(ns)
} }
@ -56,7 +56,7 @@ func (m *PrivMsgCommand) HandleNickServ(ns *NickServ) {
// //
type RegisterCommand struct { type RegisterCommand struct {
*BaseCommand BaseCommand
password string password string
email string email string
} }
@ -67,7 +67,7 @@ func NewRegisterCommand(args []string) (NickServCommand, error) {
} }
cmd := &RegisterCommand{ cmd := &RegisterCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
password: args[0], password: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
@ -100,7 +100,7 @@ func (m *RegisterCommand) HandleNickServ(ns *NickServ) {
} }
type IdentifyCommand struct { type IdentifyCommand struct {
*BaseCommand BaseCommand
password string password string
} }
@ -110,7 +110,7 @@ func NewIdentifyCommand(args []string) (NickServCommand, error) {
} }
return &IdentifyCommand{ return &IdentifyCommand{
BaseCommand: &BaseCommand{}, BaseCommand: BaseCommand{},
password: args[0], password: args[0],
}, nil }, nil
} }

View File

@ -13,8 +13,8 @@ type UserNameMap map[string]*User
type ServiceNameMap map[string]*Service type ServiceNameMap map[string]*Service
type Command interface { type Command interface {
ClientMessage Client() *Client
Handle(*Server) HandleServer(*Server)
} }
type Server struct { type Server struct {
@ -47,7 +47,7 @@ func (server *Server) receiveCommands(commands <-chan Command) {
for command := range commands { for command := range commands {
log.Printf("%s %T %+v", server.Id(), command, command) log.Printf("%s %T %+v", server.Id(), command, command)
command.Client().atime = time.Now() command.Client().atime = time.Now()
command.Handle(server) command.HandleServer(server)
} }
} }
@ -127,19 +127,19 @@ func (s *Server) DeleteChannel(channel *Channel) {
// commands // commands
// //
func (m *UnknownCommand) Handle(s *Server) { func (m *UnknownCommand) HandleServer(s *Server) {
m.Client().replies <- ErrUnknownCommand(s, m.command) m.Client().replies <- ErrUnknownCommand(s, m.command)
} }
func (m *PingCommand) Handle(s *Server) { func (m *PingCommand) HandleServer(s *Server) {
m.Client().replies <- RplPong(s) m.Client().replies <- RplPong(s)
} }
func (m *PongCommand) Handle(s *Server) { func (m *PongCommand) HandleServer(s *Server) {
// no-op // no-op
} }
func (m *PassCommand) Handle(s *Server) { func (m *PassCommand) HandleServer(s *Server) {
err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password)) err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password))
if err != nil { if err != nil {
m.Client().replies <- ErrPasswdMismatch(s) m.Client().replies <- ErrPasswdMismatch(s)
@ -150,7 +150,7 @@ func (m *PassCommand) Handle(s *Server) {
// no reply? // no reply?
} }
func (m *NickCommand) Handle(s *Server) { func (m *NickCommand) HandleServer(s *Server) {
c := m.Client() c := m.Client()
if c.user == nil { if c.user == nil {
c.replies <- RplNick(c, m.nickname) c.replies <- RplNick(c, m.nickname)
@ -162,7 +162,7 @@ func (m *NickCommand) Handle(s *Server) {
c.user.replies <- ErrNoPrivileges(s) c.user.replies <- ErrNoPrivileges(s)
} }
func (m *UserMsgCommand) Handle(s *Server) { func (m *UserMsgCommand) HandleServer(s *Server) {
c := m.Client() c := m.Client()
if c.username != "" { if c.username != "" {
c.replies <- ErrAlreadyRegistered(s) c.replies <- ErrAlreadyRegistered(s)
@ -173,7 +173,7 @@ func (m *UserMsgCommand) Handle(s *Server) {
s.tryRegister(c) s.tryRegister(c)
} }
func (m *QuitCommand) Handle(s *Server) { func (m *QuitCommand) HandleServer(s *Server) {
c := m.Client() c := m.Client()
user := c.user user := c.user
@ -191,7 +191,7 @@ func (m *QuitCommand) Handle(s *Server) {
user.LogoutClient(c) user.LogoutClient(c)
if !user.HasClients() { if !user.HasClients() {
cmd := &PartCommand{ cmd := &PartCommand{
BaseCommand: &BaseCommand{c}, BaseCommand: BaseCommand{c},
} }
for channel := range user.channels { for channel := range user.channels {
channel.commands <- cmd 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() c := m.Client()
if c.user == nil { if c.user == nil {
@ -211,7 +211,7 @@ func (m *JoinCommand) Handle(s *Server) {
if m.zero { if m.zero {
cmd := &PartCommand{ cmd := &PartCommand{
BaseCommand: &BaseCommand{c}, BaseCommand: BaseCommand{c},
} }
for channel := range c.user.channels { for channel := range c.user.channels {
channel.commands <- cmd 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 user := m.Client().user
if user == nil { 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 user := m.Client().user
if user == nil { if user == nil {
@ -263,7 +263,7 @@ func (m *TopicCommand) Handle(s *Server) {
channel.commands <- m channel.commands <- m
} }
func (m *PrivMsgCommand) Handle(s *Server) { func (m *PrivMsgCommand) HandleServer(s *Server) {
service := s.services[m.target] service := s.services[m.target]
if service != nil { if service != nil {
service.commands <- m service.commands <- m
@ -296,6 +296,6 @@ func (m *PrivMsgCommand) Handle(s *Server) {
target.commands <- m target.commands <- m
} }
func (m *ModeCommand) Handle(s *Server) { func (m *ModeCommand) HandleServer(s *Server) {
m.Client().replies <- RplUModeIs(s, m.Client()) m.Client().replies <- RplUModeIs(s, m.Client())
} }

View File

@ -10,28 +10,27 @@ type ServiceCommand interface {
HandleService(*Service) HandleService(*Service)
} }
type PrivMsgCommandFunc func(*PrivMsgCommand)
type Service struct { type Service struct {
server *Server server *Server
name string name string
commands chan<- ServiceCommand 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) commands := make(chan ServiceCommand)
service := &Service{ service := &Service{
server: s, server: s,
name: name, name: name,
commands: commands, commands: commands,
Handle: Handle,
} }
go service.receiveCommands(commands) go service.receiveCommands(commands)
s.services[name] = service s.services[name] = service
return service return service
} }
func (service *Service) HandleMsg(m *PrivMsgCommand) {
}
func (service *Service) receiveCommands(commands <-chan ServiceCommand) { func (service *Service) receiveCommands(commands <-chan ServiceCommand) {
for command := range commands { for command := range commands {
log.Printf("%s %T %+V", service.Id(), command, command) 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) { func (m *PrivMsgCommand) HandleService(s *Service) {
s.Handle(m) s.HandleMsg(m)
} }