add data structures for decoding mode messages

This commit is contained in:
Jeremy Latt 2014-02-08 14:20:23 -08:00
parent b9cb539219
commit 3f9495cda0
4 changed files with 75 additions and 10 deletions

View File

@ -6,7 +6,7 @@ import (
) )
func main() { func main() {
name := flag.String("name", "localhost", "A name for the server") name := flag.String("name", "ergonomadic", "A name for the server")
listen := flag.String("listen", ":6667", "interface to listen on") listen := flag.String("listen", ":6667", "interface to listen on")
flag.BoolVar(&irc.DEBUG_NET, "dnet", false, "debug net") flag.BoolVar(&irc.DEBUG_NET, "dnet", false, "debug net")
flag.BoolVar(&irc.DEBUG_CLIENT, "dclient", false, "debug client") flag.BoolVar(&irc.DEBUG_CLIENT, "dclient", false, "debug client")

View File

@ -13,6 +13,7 @@ type Client struct {
channels ChannelSet channels ChannelSet
conn net.Conn conn net.Conn
hostname string hostname string
invisible bool
nick string nick string
realname string realname string
registered bool registered bool
@ -30,11 +31,12 @@ func NewClient(server *Server, conn net.Conn) *Client {
replies := make(chan Reply) replies := make(chan Reply)
client := &Client{ client := &Client{
channels: make(ChannelSet), channels: make(ChannelSet),
conn: conn, conn: conn,
hostname: LookupHostname(conn.RemoteAddr()), hostname: LookupHostname(conn.RemoteAddr()),
replies: replies, replies: replies,
server: server, server: server,
serverPass: server.password == "",
} }
go client.readConn(read) go client.readConn(read)
@ -86,6 +88,9 @@ func (c *Client) Nick() string {
} }
func (c *Client) UModeString() string { func (c *Client) UModeString() string {
if c.invisible {
return "i"
}
return "" return ""
} }

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"unicode/utf8"
) )
type Command interface { type Command interface {
@ -371,14 +372,52 @@ func NewTopicCommand(args []string) (EditableCommand, error) {
return msg, nil return msg, nil
} }
type Mode rune
const (
Away Mode = 'a'
Invisible Mode = 'i'
WallOps Mode = 'w'
Restricted Mode = 'r'
Operator Mode = 'o'
LocalOperator Mode = 'O'
ServerNotice Mode = 's'
)
type ModeChange struct {
mode Mode
add bool // false => remove
}
func (change *ModeChange) String() string {
sig := "+"
if !change.add {
sig = "-"
}
return fmt.Sprintf("%s%s", sig, change.mode)
}
type ModeCommand struct { type ModeCommand struct {
BaseCommand BaseCommand
nickname string nickname string
modes string changes []ModeChange
} }
func (cmd *ModeCommand) String() string { func (cmd *ModeCommand) String() string {
return fmt.Sprintf("MODE(nickname=%s, modes=%s)", cmd.nickname, cmd.modes) return fmt.Sprintf("MODE(nickname=%s, changes=%s)", cmd.nickname, cmd.changes)
}
func stringToRunes(str string) <-chan rune {
runes := make(chan rune)
go func() {
for len(str) > 0 {
rune, size := utf8.DecodeRuneInString(str)
runes <- rune
str = str[size:]
}
close(runes)
}()
return runes
} }
func NewModeCommand(args []string) (EditableCommand, error) { func NewModeCommand(args []string) (EditableCommand, error) {
@ -388,10 +427,26 @@ func NewModeCommand(args []string) (EditableCommand, error) {
cmd := &ModeCommand{ cmd := &ModeCommand{
nickname: args[0], nickname: args[0],
changes: make([]ModeChange,
utf8.RuneCountInString(strings.Join(args[1:], ""))-len(args[1:])),
} }
if len(args) > 1 { index := 0
cmd.modes = args[1] for _, arg := range args[1:] {
modeChange := stringToRunes(arg)
sig := <-modeChange
if sig != '+' && sig != '-' {
return nil, ErrParseCommand
}
add := sig == '+'
for mode := range modeChange {
cmd.changes[index] = ModeChange{
mode: Mode(mode),
add: add,
}
index += 1
}
} }
return cmd, nil return cmd, nil

View File

@ -266,5 +266,10 @@ func (m *PrivMsgCommand) HandleServer(s *Server) {
} }
func (m *ModeCommand) HandleServer(s *Server) { func (m *ModeCommand) HandleServer(s *Server) {
for _, change := range m.changes {
if change.mode == Invisible {
m.Client().invisible = change.add
}
}
m.Client().replies <- RplUModeIs(s, m.Client()) m.Client().replies <- RplUModeIs(s, m.Client())
} }