Make NickServ actually work.

This commit is contained in:
Jeremy Latt 2013-05-11 13:55:01 -07:00
parent 65af2b4320
commit 2ff93d74be
6 changed files with 103 additions and 40 deletions

View File

@ -44,11 +44,15 @@ func NewClient(server *Server, conn net.Conn) *Client {
func (c *Client) readConn(recv <-chan string) { func (c *Client) readConn(recv <-chan string) {
for str := range recv { for str := range recv {
log.Printf("%s > %s", c.Id(), str) log.Printf("%s → %s", c.conn.RemoteAddr(), str)
m, err := ParseCommand(str) m, err := ParseCommand(str)
if err != nil { if err != nil {
c.Replies() <- ErrNeedMoreParams(c.server, str) if err == NotEnoughArgsError {
c.Replies() <- ErrNeedMoreParams(c.server, str)
} else {
c.Replies() <- ErrUnknownCommand(c.server, str)
}
continue continue
} }
@ -60,7 +64,7 @@ func (c *Client) readConn(recv <-chan string) {
func (c *Client) writeConn(write chan<- string, replies <-chan Reply) { func (c *Client) writeConn(write chan<- string, replies <-chan Reply) {
for reply := range replies { for reply := range replies {
replyStr := reply.String(c) replyStr := reply.String(c)
log.Printf("%s < %s", c.Id(), replyStr) log.Printf("%s ← %s", c.conn.RemoteAddr(), replyStr)
write <- replyStr write <- replyStr
} }
} }
@ -112,6 +116,10 @@ func (c Client) Id() string {
return c.UserHost() return c.UserHost()
} }
func (c Client) String() string {
return c.Id()
}
func (c Client) PublicId() string { func (c Client) PublicId() string {
return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Nick(), c.server.Id()) return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Nick(), c.server.Id())
} }

View File

@ -2,6 +2,7 @@ package irc
import ( import (
"errors" "errors"
"fmt"
"strconv" "strconv"
"strings" "strings"
) )
@ -38,15 +39,15 @@ type BaseCommand struct {
client *Client client *Client
} }
func (base BaseCommand) Client() *Client { func (command BaseCommand) Client() *Client {
return base.client return command.client
} }
func (base *BaseCommand) SetClient(c *Client) { func (command *BaseCommand) SetClient(c *Client) {
if base.client != nil { if command.client != nil {
panic("SetClient called twice!") panic("SetClient called twice!")
} }
base.client = c command.client = c
} }
func ParseCommand(line string) (EditableCommand, error) { func ParseCommand(line string) (EditableCommand, error) {
@ -108,6 +109,10 @@ type PingCommand struct {
server2 string server2 string
} }
func (cmd PingCommand) String() string {
return fmt.Sprintf("PING(server=%s, server2=%s)", cmd.server, cmd.server2)
}
func NewPingCommand(args []string) (EditableCommand, error) { func NewPingCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
@ -130,6 +135,10 @@ type PongCommand struct {
server2 string server2 string
} }
func (cmd PongCommand) String() string {
return fmt.Sprintf("PONG(server1=%s, server2=%s)", cmd.server1, cmd.server2)
}
func NewPongCommand(args []string) (EditableCommand, error) { func NewPongCommand(args []string) (EditableCommand, error) {
if len(args) < 1 { if len(args) < 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
@ -168,6 +177,10 @@ type NickCommand struct {
nickname string nickname string
} }
func (m NickCommand) String() string {
return fmt.Sprintf("NICK(nickname=%s)", m.nickname)
}
func NewNickCommand(args []string) (EditableCommand, error) { func NewNickCommand(args []string) (EditableCommand, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
@ -188,6 +201,11 @@ type UserMsgCommand struct {
realname string realname string
} }
func (cmd UserMsgCommand) String() string {
return fmt.Sprintf("USER(user=%s, mode=%o, unused=%s, realname=%s)",
cmd.user, cmd.mode, cmd.unused, cmd.realname)
}
func NewUserMsgCommand(args []string) (EditableCommand, error) { func NewUserMsgCommand(args []string) (EditableCommand, error) {
if len(args) != 4 { if len(args) != 4 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
@ -212,6 +230,10 @@ type QuitCommand struct {
message string message string
} }
func (cmd QuitCommand) String() string {
return fmt.Sprintf("QUIT(message=%s)", cmd.message)
}
func NewQuitCommand(args []string) (EditableCommand, error) { func NewQuitCommand(args []string) (EditableCommand, error) {
msg := &QuitCommand{ msg := &QuitCommand{
BaseCommand: BaseCommand{}, BaseCommand: BaseCommand{},
@ -289,6 +311,10 @@ type PrivMsgCommand struct {
message string message string
} }
func (cmd PrivMsgCommand) String() string {
return fmt.Sprintf("PRIVMSG(target=%s, message=%s)", cmd.target, cmd.message)
}
func NewPrivMsgCommand(args []string) (EditableCommand, error) { func NewPrivMsgCommand(args []string) (EditableCommand, error) {
if len(args) < 2 { if len(args) < 2 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
@ -336,6 +362,10 @@ type ModeCommand struct {
modes string modes string
} }
func (cmd ModeCommand) String() string {
return fmt.Sprintf("MODE(nickname=%s, modes=%s)", cmd.nickname, cmd.modes)
}
func NewModeCommand(args []string) (EditableCommand, error) { func NewModeCommand(args []string) (EditableCommand, error) {
if len(args) == 0 { if len(args) == 0 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError

View File

@ -1,6 +1,7 @@
package irc package irc
import ( import (
"fmt"
"log" "log"
) )
@ -11,13 +12,15 @@ type NickServCommand interface {
} }
type NickServ struct { type NickServ struct {
*Service BaseService
} }
func NewNickServ(s *Server) *NickServ { func NewNickServ(s *Server) Service {
return &NickServ{ return NewService(new(NickServ), s, "NickServ")
Service: NewService(s, "NickServ"), }
}
func (ns *NickServ) SetBase(base *BaseService) {
ns.BaseService = *base
} }
var ( var (
@ -31,7 +34,7 @@ var (
// commands // commands
// //
func (ns *NickServ) HandleMsg(m *PrivMsgCommand) { func (ns *NickServ) HandlePrivMsg(m *PrivMsgCommand) {
command, args := parseLine(m.message) command, args := parseLine(m.message)
constructor := parseNickServCommandFuncs[command] constructor := parseNickServCommandFuncs[command]
if constructor == nil { if constructor == nil {
@ -46,7 +49,7 @@ func (ns *NickServ) HandleMsg(m *PrivMsgCommand) {
} }
cmd.SetClient(m.Client()) cmd.SetClient(m.Client())
log.Printf("%s %T %+v", ns.Id(), cmd, cmd) log.Printf("%s ← %s", ns, cmd)
cmd.HandleNickServ(ns) cmd.HandleNickServ(ns)
} }
@ -61,6 +64,10 @@ type RegisterCommand struct {
email string email string
} }
func (m RegisterCommand) String() string {
return fmt.Sprintf("REGISTER(email=%s, password=%s)", m.email, m.password)
}
func NewRegisterCommand(args []string) (NickServCommand, error) { func NewRegisterCommand(args []string) (NickServCommand, error) {
if len(args) == 0 { if len(args) == 0 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
@ -104,6 +111,10 @@ type IdentifyCommand struct {
password string password string
} }
func (m IdentifyCommand) String() string {
return fmt.Sprintf("IDENTIFY(password=%s)", m.password)
}
func NewIdentifyCommand(args []string) (NickServCommand, error) { func NewIdentifyCommand(args []string) (NickServCommand, error) {
if len(args) == 0 { if len(args) == 0 {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError

View File

@ -100,7 +100,7 @@ func RplWelcome(source Identifier, client *Client) Reply {
func RplYourHost(server *Server, target *Client) Reply { func RplYourHost(server *Server, target *Client) Reply {
return NewNumericReply(server, RPL_YOURHOST, return NewNumericReply(server, RPL_YOURHOST,
"Your host is %s, running version %s", server.hostname, VERSION) "Your host is %s, running version %s", server.name, VERSION)
} }
func RplCreated(server *Server) Reply { func RplCreated(server *Server) Reply {

View File

@ -10,7 +10,7 @@ import (
type ClientNameMap map[string]*Client type ClientNameMap map[string]*Client
type ChannelNameMap map[string]*Channel type ChannelNameMap map[string]*Channel
type UserNameMap map[string]*User type UserNameMap map[string]*User
type ServiceNameMap map[string]*Service type ServiceNameMap map[string]Service
type Server struct { type Server struct {
hostname string hostname string
@ -40,7 +40,7 @@ func NewServer(name string) *Server {
func (server *Server) receiveCommands(commands <-chan Command) { 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 ← %s %s", server, command.Client(), command)
command.Client().atime = time.Now() command.Client().atime = time.Now()
command.HandleServer(server) command.HandleServer(server)
} }
@ -103,7 +103,11 @@ func (s *Server) tryRegister(c *Client) {
} }
func (s Server) Id() string { func (s Server) Id() string {
return s.hostname return s.name
}
func (s Server) String() string {
return s.Id()
} }
func (s Server) PublicId() string { func (s Server) PublicId() string {
@ -122,7 +126,7 @@ func (s *Server) DeleteChannel(channel *Channel) {
// commands // commands
// //
func (m *UnknownCommand) HandleServer(s *Server) { func (m UnknownCommand) HandleServer(s *Server) {
m.Client().Replies() <- ErrUnknownCommand(s, m.command) m.Client().Replies() <- ErrUnknownCommand(s, m.command)
} }

View File

@ -7,60 +7,70 @@ import (
type ServiceCommand interface { type ServiceCommand interface {
Command Command
HandleService(*Service) HandleService(Service)
} }
type Service struct { type Service interface {
Identifier
Commands() chan<- ServiceCommand
HandlePrivMsg(*PrivMsgCommand)
}
type EditableService interface {
Service
SetBase(*BaseService)
}
type BaseService struct {
server *Server server *Server
name string name string
commands chan<- ServiceCommand commands chan<- ServiceCommand
} }
func NewService(s *Server, name string) *Service { func NewService(service EditableService, s *Server, name string) Service {
commands := make(chan ServiceCommand) commands := make(chan ServiceCommand)
service := &Service{ base := &BaseService{
server: s, server: s,
name: name, name: name,
commands: commands, commands: commands,
} }
go service.receiveCommands(commands) go receiveCommands(service, commands)
service.SetBase(base)
s.services[name] = service s.services[name] = service
return service return service
} }
func (service *Service) HandleMsg(m *PrivMsgCommand) {} func receiveCommands(service Service, 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 ← %s %s", service.Id(), command.Client(), command)
command.HandleService(service) command.HandleService(service)
} }
} }
func (service Service) Id() string { func (service BaseService) Id() string {
return fmt.Sprintf("%s!%s@%s", service.name, service.name, service.server.name) return fmt.Sprintf("%s!%s@%s", service.name, service.name, service.server.name)
} }
func (service Service) PublicId() string { func (service BaseService) String() string {
return service.Id() return service.Id()
} }
func (service Service) Nick() string { func (service BaseService) PublicId() string {
return service.Id()
}
func (service BaseService) Nick() string {
return service.name return service.name
} }
func (service *Service) Reply(client *Client, message string) { func (service *BaseService) Reply(client *Client, message string) {
client.Replies() <- RplPrivMsg(service, client, message) client.Replies() <- RplPrivMsg(service, client, message)
} }
func (service Service) Commands() chan<- ServiceCommand { func (service BaseService) Commands() chan<- ServiceCommand {
return service.commands return service.commands
} }
// func (m *PrivMsgCommand) HandleService(service Service) {
// commands service.HandlePrivMsg(m)
//
func (m *PrivMsgCommand) HandleService(s *Service) {
s.HandleMsg(m)
} }