use ModeOp everywhere

This commit is contained in:
Jeremy Latt 2014-02-08 22:42:14 -08:00
parent 93f4b6859a
commit 20257ec624
4 changed files with 85 additions and 86 deletions

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"unicode/utf8"
) )
type editableCommand interface { type editableCommand interface {
@ -374,15 +373,11 @@ func NewTopicCommand(args []string) (editableCommand, error) {
type ModeChange struct { type ModeChange struct {
mode UserMode mode UserMode
add bool // false => remove op ModeOp
} }
func (change *ModeChange) String() string { func (change *ModeChange) String() string {
sig := "+" return fmt.Sprintf("%s%s", change.op, change.mode)
if !change.add {
sig = "-"
}
return fmt.Sprintf("%s%s", sig, change.mode)
} }
type ModeCommand struct { type ModeCommand struct {
@ -391,21 +386,32 @@ type ModeCommand struct {
changes []ModeChange changes []ModeChange
} }
func (cmd *ModeCommand) String() string { // MODE <nickname> *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
return fmt.Sprintf("MODE(nickname=%s, changes=%s)", cmd.nickname, cmd.changes) func NewUserModeCommand(args []string) (editableCommand, error) {
cmd := &ModeCommand{
nickname: args[0],
changes: make([]ModeChange, 0),
} }
func stringToRunes(str string) <-chan rune { for _, modeChange := range args[1:] {
runes := make(chan rune) op := ModeOp(modeChange[0])
go func() { if (op != Add) && (op != Remove) {
for len(str) > 0 { return nil, ErrParseCommand
rune, size := utf8.DecodeRuneInString(str)
runes <- rune
str = str[size:]
} }
close(runes)
}() for _, mode := range modeChange[1:] {
return runes cmd.changes = append(cmd.changes, ModeChange{
mode: UserMode(mode),
op: op,
})
}
}
return cmd, nil
}
func (cmd *ModeCommand) String() string {
return fmt.Sprintf("MODE(nickname=%s, changes=%s)", cmd.nickname, cmd.changes)
} }
type ChannelModeOp struct { type ChannelModeOp struct {
@ -434,23 +440,22 @@ func NewChannelModeCommand(args []string) (editableCommand, error) {
for len(args) > 0 { for len(args) > 0 {
modeArg := args[0] modeArg := args[0]
op := List
switch modeArg[0] { op := ModeOp(modeArg[0])
case '+': if (op == Add) || (op == Remove) {
op = Add
modeArg = modeArg[1:]
case '-':
op = Remove
modeArg = modeArg[1:] modeArg = modeArg[1:]
} else {
op = List
} }
skipArgs := 1 skipArgs := 1
for mode := range stringToRunes(modeArg) { for _, mode := range modeArg {
modeOp := ChannelModeOp{ modeOp := ChannelModeOp{
mode: ChannelMode(mode), mode: ChannelMode(mode),
op: op, op: op,
} }
switch modeOp.mode { switch modeOp.mode {
case Key, BanMask, ExceptionMask, InviteMask: case Key, BanMask, ExceptionMask, InviteMask, UserLimit:
if len(args) > skipArgs { if len(args) > skipArgs {
modeOp.arg = args[skipArgs] modeOp.arg = args[skipArgs]
skipArgs += 1 skipArgs += 1
@ -468,35 +473,6 @@ func (msg *ChannelModeCommand) String() string {
return fmt.Sprintf("MODE(channel=%s, modeOps=%s)", msg.channel, msg.modeOps) return fmt.Sprintf("MODE(channel=%s, modeOps=%s)", msg.channel, msg.modeOps)
} }
// MODE <nickname> *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
func NewUserModeCommand(args []string) (editableCommand, error) {
cmd := &ModeCommand{
nickname: args[0],
changes: make([]ModeChange,
utf8.RuneCountInString(strings.Join(args[1:], ""))-len(args[1:])),
}
index := 0
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: UserMode(mode),
add: add,
}
index += 1
}
}
return cmd, nil
}
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
@ -543,7 +519,7 @@ func (msg *WhoisCommand) String() string {
type WhoCommand struct { type WhoCommand struct {
BaseCommand BaseCommand
mask string mask Mask
operatorOnly bool operatorOnly bool
} }
@ -552,7 +528,7 @@ func NewWhoCommand(args []string) (editableCommand, error) {
cmd := &WhoCommand{} cmd := &WhoCommand{}
if len(args) > 0 { if len(args) > 0 {
cmd.mask = args[0] cmd.mask = Mask(args[0])
} }
if (len(args) > 1) && (args[1] == "o") { if (len(args) > 1) && (args[1] == "o") {

View File

@ -158,32 +158,32 @@ const (
RPL_PRIVMSG = "PRIVMSG" RPL_PRIVMSG = "PRIVMSG"
RPL_QUIT = "QUIT" RPL_QUIT = "QUIT"
List ModeOp = 'l' Add ModeOp = '+'
Add ModeOp = 'a' List ModeOp = '='
Remove ModeOp = 'r' Remove ModeOp = '-'
Away UserMode = 'a' Away UserMode = 'a'
Invisible UserMode = 'i' Invisible UserMode = 'i'
WallOps UserMode = 'w'
Restricted UserMode = 'r'
Operator UserMode = 'o'
LocalOperator UserMode = 'O' LocalOperator UserMode = 'O'
Operator UserMode = 'o'
Restricted UserMode = 'r'
ServerNotice UserMode = 's' ServerNotice UserMode = 's'
WallOps UserMode = 'w'
Anonymous ChannelMode = 'a' Anonymous ChannelMode = 'a'
BanMask ChannelMode = 'b' // arg
ExceptionMask ChannelMode = 'e' // arg
InviteMask ChannelMode = 'i' // arg
InviteOnly ChannelMode = 'i' InviteOnly ChannelMode = 'i'
Key ChannelMode = 'k' // arg
Moderated ChannelMode = 'm' Moderated ChannelMode = 'm'
NoOutside ChannelMode = 'n' NoOutside ChannelMode = 'n'
Quiet ChannelMode = 'q'
Private ChannelMode = 'p'
Secret ChannelMode = 's'
ReOp ChannelMode = 'r'
OpOnlyTopic ChannelMode = 't' OpOnlyTopic ChannelMode = 't'
Key ChannelMode = 'k' Private ChannelMode = 'p'
UserLimit ChannelMode = 'l' Quiet ChannelMode = 'q'
BanMask ChannelMode = 'b' ReOp ChannelMode = 'r'
ExceptionMask ChannelMode = 'e' Secret ChannelMode = 's'
InviteMask ChannelMode = 'i' UserLimit ChannelMode = 'l' // arg
ChannelCreator UserChannelMode = 'O' ChannelCreator UserChannelMode = 'O'
ChannelOperator UserChannelMode = 'o' ChannelOperator UserChannelMode = 'o'

View File

@ -271,7 +271,12 @@ func (m *ModeCommand) HandleServer(s *Server) {
if client.Nick() == m.nickname { if client.Nick() == m.nickname {
for _, change := range m.changes { for _, change := range m.changes {
if change.mode == Invisible { if change.mode == Invisible {
client.invisible = change.add switch change.op {
case Add:
client.invisible = true
case Remove:
client.invisible = false
}
} }
} }
client.replies <- RplUModeIs(s, client) client.replies <- RplUModeIs(s, client)
@ -320,21 +325,22 @@ func (msg *WhoCommand) HandleServer(server *Server) {
client := msg.Client() client := msg.Client()
// TODO implement wildcard matching // TODO implement wildcard matching
if msg.mask == "" { mask := string(msg.mask)
if mask == "" {
for _, channel := range server.channels { for _, channel := range server.channels {
whoChannel(client, server, channel) whoChannel(client, server, channel)
} }
} else if IsChannel(msg.mask) { } else if IsChannel(mask) {
channel := server.channels[msg.mask] channel := server.channels[mask]
if channel != nil { if channel != nil {
whoChannel(client, server, channel) whoChannel(client, server, channel)
} }
} else { } else {
mclient := server.clients[msg.mask] mclient := server.clients[mask]
if mclient != nil { if mclient != nil {
client.replies <- RplWhoReply(server, mclient.channels.First(), mclient) client.replies <- RplWhoReply(server, mclient.channels.First(), mclient)
} }
} }
client.replies <- RplEndOfWho(server, msg.mask) client.replies <- RplEndOfWho(server, mask)
} }

View File

@ -4,16 +4,31 @@ import (
"fmt" "fmt"
) )
//
// simple types // simple types
//
type ModeOp rune // a string with wildcards
type UserMode rune
type ChannelMode rune
type UserChannelMode rune
type Mask string type Mask string
// interfaces // add, remove, list modes
type ModeOp rune
// user mode flags
type UserMode rune
// channel mode flags
type ChannelMode rune
// user-channel mode flags
type UserChannelMode rune
//
// interfaces
//
// commands the server understands
// TODO rename ServerCommand
type Command interface { type Command interface {
Client() *Client Client() *Client
Source() Identifier Source() Identifier
@ -21,7 +36,9 @@ type Command interface {
HandleServer(*Server) HandleServer(*Server)
} }
//
// structs // structs
//
type UserMask struct { type UserMask struct {
nickname Mask nickname Mask