1
0
Fork 0
forked from External/ergo

cleanup and reorganization

This commit is contained in:
Jeremy Latt 2012-12-09 12:51:50 -08:00
parent 2dba5f4c47
commit 55f7c89468
8 changed files with 254 additions and 196 deletions

View file

@ -1,15 +1,30 @@
package irc
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
type Message interface {
Handle(s *Server, c *Client)
}
var (
ErrNotEnoughArgs = errors.New("not enough arguments")
ErrUModeUnknownFlag = errors.New("unknown umode flag")
)
// unknown
type UnknownMessage struct {
command string
}
// NB: no constructor, created on demand in parser for invalid messages.
func (m *UnknownMessage) Handle(s *Server, c *Client) {
c.send <- ErrUnknownCommand(s, m.command)
}
@ -21,6 +36,17 @@ type PingMessage struct {
server2 string
}
func NewPingMessage(args []string) (Message, error) {
if len(args) < 1 {
return nil, ErrNotEnoughArgs
}
msg := &PingMessage{server: args[0]}
if len(args) > 1 {
msg.server2 = args[1]
}
return msg, nil
}
func (m *PingMessage) Handle(s *Server, c *Client) {
c.send <- RplPong(s)
}
@ -32,8 +58,19 @@ type PongMessage struct {
server2 string
}
func NewPongMessage(args []string) (Message, error) {
if len(args) < 1 {
return nil, ErrNotEnoughArgs
}
message := &PongMessage{server1: args[0]}
if len(args) > 1 {
message.server2 = args[1]
}
return message, nil
}
func (m *PongMessage) Handle(s *Server, c *Client) {
// TODO update client atime
// no-op
}
// NICK
@ -42,6 +79,13 @@ type NickMessage struct {
nickname string
}
func NewNickMessage(args []string) (Message, error) {
if len(args) != 1 {
return nil, ErrNotEnoughArgs
}
return &NickMessage{args[0]}, nil
}
func (m *NickMessage) Handle(s *Server, c *Client) {
s.ChangeNick(c, m.nickname)
}
@ -55,8 +99,24 @@ type UserMessage struct {
realname string
}
func NewUserMessage(args []string) (Message, error) {
if len(args) != 4 {
return nil, ErrNotEnoughArgs
}
msg := &UserMessage{
user: args[0],
unused: args[2],
realname: args[3],
}
mode, err := strconv.ParseUint(args[1], 10, 8)
if err == nil {
msg.mode = uint8(mode)
}
return msg, nil
}
func (m *UserMessage) Handle(s *Server, c *Client) {
s.Register(c, m.user, m.realname)
s.UserLogin(c, m.user, m.realname)
}
// QUIT
@ -65,6 +125,14 @@ type QuitMessage struct {
message string
}
func NewQuitMessage(args []string) (Message, error) {
msg := &QuitMessage{}
if len(args) > 0 {
msg.message = args[0]
}
return msg, nil
}
func (m *QuitMessage) Handle(s *Server, c *Client) {
s.Quit(c, m.message)
}
@ -76,6 +144,28 @@ type ModeMessage struct {
modes []string
}
var MODE_RE = regexp.MustCompile("^[-+][a-zA-Z]+$")
func NewModeMessage(args []string) (Message, error) {
if len(args) < 1 {
return nil, ErrNotEnoughArgs
}
msg := &ModeMessage{
nickname: args[0],
}
for _, arg := range args[1:] {
if !MODE_RE.MatchString(arg) {
return nil, ErrUModeUnknownFlag
}
prefix := arg[0]
for _, c := range arg[1:] {
mode := fmt.Sprintf("%c%c", prefix, c)
msg.modes = append(msg.modes, mode)
}
}
return msg, nil
}
func (m *ModeMessage) Handle(s *Server, c *Client) {
if m.nickname != c.nick {
c.send <- ErrUsersDontMatch(s)
@ -92,6 +182,22 @@ type JoinMessage struct {
zero bool
}
func NewJoinMessage(args []string) (Message, error) {
msg := &JoinMessage{}
if len(args) > 0 {
if args[0] == "0" {
msg.zero = true
} else {
msg.channels = strings.Split(args[0], ",")
}
if len(args) > 1 {
msg.keys = strings.Split(args[1], ",")
}
}
return msg, nil
}
func (m *JoinMessage) Handle(s *Server, c *Client) {
if m.zero {
for channel := range c.channels {
@ -116,6 +222,17 @@ type PartMessage struct {
message string
}
func NewPartMessage(args []string) (Message, error) {
if len(args) < 1 {
return nil, ErrNotEnoughArgs
}
msg := &PartMessage{channels: strings.Split(args[0], ",")}
if len(args) > 1 {
msg.message = args[1]
}
return msg, nil
}
func (m *PartMessage) Handle(s *Server, c *Client) {
for _, chname := range m.channels {
channel := s.channels[chname]
@ -136,6 +253,16 @@ type PrivMsgMessage struct {
message string
}
func NewPrivMsgMessage(args []string) (Message, error) {
if len(args) < 2 {
return nil, ErrNotEnoughArgs
}
return &PrivMsgMessage{
target: args[0],
message: args[1],
}, nil
}
func (m *PrivMsgMessage) TargetIsChannel() bool {
switch m.target[0] {
case '&', '#', '+', '!':
@ -169,6 +296,17 @@ type TopicMessage struct {
topic string
}
func NewTopicMessage(args []string) (Message, error) {
if len(args) < 1 {
return nil, ErrNotEnoughArgs
}
msg := &TopicMessage{channel: args[0]}
if len(args) > 1 {
msg.topic = args[1]
}
return msg, nil
}
func (m *TopicMessage) Handle(s *Server, c *Client) {
channel := s.channels[m.channel]
if channel == nil {