mirror of
				https://github.com/fluffle/goirc
				synced 2025-10-31 02:08:03 +00:00 
			
		
		
		
	Handlers/Commands now use the container/list.
Re introduced strip nick and strip prefix for SimpleCommands Fixed tests.
This commit is contained in:
		
							parent
							
								
									e8eba53828
								
							
						
					
					
						commit
						e4da830c55
					
				
					 5 changed files with 134 additions and 208 deletions
				
			
		|  | @ -21,7 +21,7 @@ type Conn struct { | |||
| 	password string | ||||
| 
 | ||||
| 	// Handlers and Commands | ||||
| 	handlers *hSet | ||||
| 	handlers *handlerSet | ||||
| 	commands *commandList | ||||
| 
 | ||||
| 	// State tracker for nicks and channels | ||||
|  | @ -54,6 +54,9 @@ type Conn struct { | |||
| 	// Client->server ping frequency, in seconds. Defaults to 3m. | ||||
| 	PingFreq time.Duration | ||||
| 
 | ||||
| 	// Controls what is stripped from line.Args[1] for Commands | ||||
| 	CommandStripNick, SimpleCommandStripPrefix bool | ||||
| 
 | ||||
| 	// Set this to true to disable flood protection and false to re-enable | ||||
| 	Flood bool | ||||
| 
 | ||||
|  | @ -81,7 +84,7 @@ func Client(nick string, args ...string) *Conn { | |||
| 		cSend:      make(chan bool), | ||||
| 		cLoop:      make(chan bool), | ||||
| 		cPing:      make(chan bool), | ||||
| 		handlers:   handlerSet(), | ||||
| 		handlers:   newHandlerSet(), | ||||
| 		commands:   newCommandList(), | ||||
| 		stRemovers: make([]Remover, 0, len(stHandlers)), | ||||
| 		PingFreq:   3 * time.Minute, | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| package client | ||||
| 
 | ||||
| import ( | ||||
| 	"container/list" | ||||
| 	"fmt" | ||||
| 	"github.com/fluffle/golog/logging" | ||||
| 	"math" | ||||
|  | @ -31,163 +32,119 @@ func (r RemoverFunc) Remove() { | |||
| 	r() | ||||
| } | ||||
| 
 | ||||
| type hList struct { | ||||
| 	start, end *hNode | ||||
| type handlerElement struct { | ||||
| 	event   string | ||||
| 	handler Handler | ||||
| } | ||||
| 
 | ||||
| type hNode struct { | ||||
| 	next, prev *hNode | ||||
| 	set        *hSet | ||||
| 	event      string | ||||
| 	handler    Handler | ||||
| } | ||||
| 
 | ||||
| func (hn *hNode) Handle(conn *Conn, line *Line) { | ||||
| 	hn.handler.Handle(conn, line) | ||||
| } | ||||
| 
 | ||||
| func (hn *hNode) Remove() { | ||||
| 	hn.set.remove(hn) | ||||
| } | ||||
| 
 | ||||
| type hSet struct { | ||||
| 	set map[string]*hList | ||||
| type handlerSet struct { | ||||
| 	set map[string]*list.List | ||||
| 	sync.RWMutex | ||||
| } | ||||
| 
 | ||||
| func handlerSet() *hSet { | ||||
| 	return &hSet{set: make(map[string]*hList)} | ||||
| func newHandlerSet() *handlerSet { | ||||
| 	return &handlerSet{set: make(map[string]*list.List)} | ||||
| } | ||||
| 
 | ||||
| func (hs *hSet) add(ev string, h Handler) Remover { | ||||
| func (hs *handlerSet) add(event string, handler Handler) Remover { | ||||
| 	hs.Lock() | ||||
| 	defer hs.Unlock() | ||||
| 	ev = strings.ToLower(ev) | ||||
| 	l, ok := hs.set[ev] | ||||
| 	event = strings.ToLower(event) | ||||
| 	l, ok := hs.set[event] | ||||
| 	if !ok { | ||||
| 		l = &hList{} | ||||
| 		l = list.New() | ||||
| 		hs.set[event] = l | ||||
| 	} | ||||
| 	hn := &hNode{ | ||||
| 		set:     hs, | ||||
| 		event:   ev, | ||||
| 		handler: h, | ||||
| 	} | ||||
| 	if !ok { | ||||
| 		l.start = hn | ||||
| 	} else { | ||||
| 		hn.prev = l.end | ||||
| 		l.end.next = hn | ||||
| 	} | ||||
| 	l.end = hn | ||||
| 	hs.set[ev] = l | ||||
| 	return hn | ||||
| 	element := l.PushBack(&handlerElement{event, handler}) | ||||
| 	return RemoverFunc(func() { | ||||
| 		hs.remove(element) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (hs *hSet) remove(hn *hNode) { | ||||
| func (hs *handlerSet) remove(element *list.Element) { | ||||
| 	hs.Lock() | ||||
| 	defer hs.Unlock() | ||||
| 	l, ok := hs.set[hn.event] | ||||
| 	h := element.Value.(*handlerElement) | ||||
| 	l, ok := hs.set[h.event] | ||||
| 	if !ok { | ||||
| 		logging.Error("Removing node for unknown event '%s'", hn.event) | ||||
| 		logging.Error("Removing node for unknown event '%s'", h.event) | ||||
| 		return | ||||
| 	} | ||||
| 	if hn.next == nil { | ||||
| 		l.end = hn.prev | ||||
| 	} else { | ||||
| 		hn.next.prev = hn.prev | ||||
| 	} | ||||
| 	if hn.prev == nil { | ||||
| 		l.start = hn.next | ||||
| 	} else { | ||||
| 		hn.prev.next = hn.next | ||||
| 	} | ||||
| 	hn.next = nil | ||||
| 	hn.prev = nil | ||||
| 	hn.set = nil | ||||
| 	if l.start == nil || l.end == nil { | ||||
| 		delete(hs.set, hn.event) | ||||
| 	l.Remove(element) | ||||
| 	if l.Len() == 0 { | ||||
| 		delete(hs.set, h.event) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (hs *hSet) dispatch(conn *Conn, line *Line) { | ||||
| func (hs *handlerSet) dispatch(conn *Conn, line *Line) { | ||||
| 	hs.RLock() | ||||
| 	defer hs.RUnlock() | ||||
| 	ev := strings.ToLower(line.Cmd) | ||||
| 	list, ok := hs.set[ev] | ||||
| 	event := strings.ToLower(line.Cmd) | ||||
| 	l, ok := hs.set[event] | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
| 	for hn := list.start; hn != nil; hn = hn.next { | ||||
| 		go hn.Handle(conn, line) | ||||
| 
 | ||||
| 	for e := l.Front(); e != nil; e = e.Next() { | ||||
| 		h := e.Value.(*handlerElement) | ||||
| 		go h.handler.Handle(conn, line) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type command struct { | ||||
| 	handler  Handler | ||||
| 	set      *commandList | ||||
| type commandElement struct { | ||||
| 	regex    string | ||||
| 	handler  Handler | ||||
| 	priority int | ||||
| } | ||||
| 
 | ||||
| func (c *command) Handle(conn *Conn, line *Line) { | ||||
| 	c.handler.Handle(conn, line) | ||||
| } | ||||
| 
 | ||||
| func (c *command) Remove() { | ||||
| 	c.set.remove(c) | ||||
| } | ||||
| 
 | ||||
| type commandList struct { | ||||
| 	set []*command | ||||
| 	list *list.List | ||||
| 	sync.RWMutex | ||||
| } | ||||
| 
 | ||||
| func newCommandList() *commandList { | ||||
| 	return &commandList{} | ||||
| 	return &commandList{list: list.New()} | ||||
| } | ||||
| 
 | ||||
| func (cl *commandList) add(regex string, handler Handler, priority int) Remover { | ||||
| 	cl.Lock() | ||||
| 	defer cl.Unlock() | ||||
| 	c := &command{ | ||||
| 		handler:  handler, | ||||
| 		set:      cl, | ||||
| 	c := &commandElement{ | ||||
| 		regex:    regex, | ||||
| 		handler:  handler, | ||||
| 		priority: priority, | ||||
| 	} | ||||
| 	// Check for exact regex matches. This will filter out any repeated SimpleCommands. | ||||
| 	for _, c := range cl.set { | ||||
| 	for e := cl.list.Front(); e != nil; e = e.Next() { | ||||
| 		c := e.Value.(*commandElement) | ||||
| 		if c.regex == regex { | ||||
| 			logging.Error("Command prefix '%s' already registered.", regex) | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	cl.set = append(cl.set, c) | ||||
| 	return c | ||||
| 	element := cl.list.PushBack(c) | ||||
| 	return RemoverFunc(func() { | ||||
| 		cl.remove(element) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (cl *commandList) remove(c *command) { | ||||
| func (cl *commandList) remove(element *list.Element) { | ||||
| 	cl.Lock() | ||||
| 	defer cl.Unlock() | ||||
| 	for index, value := range cl.set { | ||||
| 		if value == c { | ||||
| 			copy(cl.set[index:], cl.set[index+1:]) | ||||
| 			cl.set = cl.set[:len(cl.set)-1] | ||||
| 			c.set = nil | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	cl.list.Remove(element) | ||||
| } | ||||
| 
 | ||||
| // Matches the command with the highest priority. | ||||
| func (cl *commandList) match(txt string) (handler Handler) { | ||||
| func (cl *commandList) match(text string) (handler Handler) { | ||||
| 	cl.RLock() | ||||
| 	defer cl.RUnlock() | ||||
| 	maxPriority := math.MinInt32 | ||||
| 	for _, c := range cl.set { | ||||
| 	text = strings.ToLower(text) | ||||
| 	for e := cl.list.Front(); e != nil; e = e.Next() { | ||||
| 		c := e.Value.(*commandElement) | ||||
| 		if c.priority > maxPriority { | ||||
| 			if regex, error := regexp.Compile(c.regex); error == nil { | ||||
| 				if regex.MatchString(txt) { | ||||
| 				if regex.MatchString(text) { | ||||
| 					maxPriority = c.priority | ||||
| 					handler = c.handler | ||||
| 				} | ||||
|  | @ -226,7 +183,18 @@ var SimpleCommandRegex string = `^!%v(\s|$)` | |||
| // !roll | ||||
| // Because simple commands are simple, they get the highest priority. | ||||
| func (conn *Conn) SimpleCommand(prefix string, handler Handler) Remover { | ||||
| 	return conn.Command(fmt.Sprintf(SimpleCommandRegex, strings.ToLower(prefix)), handler, math.MaxInt32) | ||||
| 	stripHandler := func(conn *Conn, line *Line) { | ||||
| 		text := line.Message() | ||||
| 		if conn.SimpleCommandStripPrefix { | ||||
| 			text = strings.TrimSpace(text[len(prefix):]) | ||||
| 		} | ||||
| 		if text != line.Message() { | ||||
| 			line = line.Copy() | ||||
| 			line.Args[1] = text | ||||
| 		} | ||||
| 		handler.Handle(conn, line) | ||||
| 	} | ||||
| 	return conn.Command(fmt.Sprintf(SimpleCommandRegex, strings.ToLower(prefix)), HandlerFunc(stripHandler), math.MaxInt32) | ||||
| } | ||||
| 
 | ||||
| func (conn *Conn) SimpleCommandFunc(prefix string, handlerFunc HandlerFunc) Remover { | ||||
|  | @ -256,10 +224,6 @@ func (conn *Conn) dispatch(line *Line) { | |||
| 	conn.handlers.dispatch(conn, line) | ||||
| } | ||||
| 
 | ||||
| func (conn *Conn) command(line *Line) { | ||||
| 	command := conn.commands.match(strings.ToLower(line.Message())) | ||||
| 	if command != nil { | ||||
| 		command.Handle(conn, line) | ||||
| 	} | ||||
| 
 | ||||
| func (conn *Conn) command(line *Line) Handler { | ||||
| 	return conn.commands.match(line.Message()) | ||||
| } | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import ( | |||
| ) | ||||
| 
 | ||||
| func TestHandlerSet(t *testing.T) { | ||||
| 	hs := handlerSet() | ||||
| 	hs := newHandlerSet() | ||||
| 	if len(hs.set) != 0 { | ||||
| 		t.Errorf("New set contains things!") | ||||
| 	} | ||||
|  | @ -17,66 +17,40 @@ func TestHandlerSet(t *testing.T) { | |||
| 	} | ||||
| 
 | ||||
| 	// Add one | ||||
| 	hn1 := hs.add("ONE", HandlerFunc(f)).(*hNode) | ||||
| 	hn1 := hs.add("ONE", HandlerFunc(f)) | ||||
| 	hl, ok := hs.set["one"] | ||||
| 	if len(hs.set) != 1 || !ok { | ||||
| 		t.Errorf("Set doesn't contain 'one' list after add().") | ||||
| 	} | ||||
| 	if hn1.set != hs || hn1.event != "one" || hn1.prev != nil || hn1.next != nil { | ||||
| 		t.Errorf("First node for 'one' not created correctly") | ||||
| 	} | ||||
| 	if hl.start != hn1 || hl.end != hn1 { | ||||
| 		t.Errorf("Node not added to empty 'one' list correctly.") | ||||
| 	if hl.Len() != 1 { | ||||
| 		t.Errorf("List doesn't contain 'one' after add().") | ||||
| 	} | ||||
| 
 | ||||
| 	// Add another one... | ||||
| 	hn2 := hs.add("one", HandlerFunc(f)).(*hNode) | ||||
| 	hn2 := hs.add("one", HandlerFunc(f)) | ||||
| 	if len(hs.set) != 1 { | ||||
| 		t.Errorf("Set contains more than 'one' list after add().") | ||||
| 	} | ||||
| 	if hn2.set != hs || hn2.event != "one" { | ||||
| 		t.Errorf("Second node for 'one' not created correctly") | ||||
| 	} | ||||
| 	if hn1.prev != nil || hn1.next != hn2 || hn2.prev != hn1 || hn2.next != nil { | ||||
| 		t.Errorf("Nodes for 'one' not linked correctly.") | ||||
| 	} | ||||
| 	if hl.start != hn1 || hl.end != hn2 { | ||||
| 		t.Errorf("Node not appended to 'one' list correctly.") | ||||
| 	if hl.Len() != 2 { | ||||
| 		t.Errorf("List doesn't contain second 'one' after add().") | ||||
| 	} | ||||
| 
 | ||||
| 	// Add a third one! | ||||
| 	hn3 := hs.add("one", HandlerFunc(f)).(*hNode) | ||||
| 	hn3 := hs.add("one", HandlerFunc(f)) | ||||
| 	if len(hs.set) != 1 { | ||||
| 		t.Errorf("Set contains more than 'one' list after add().") | ||||
| 	} | ||||
| 	if hn3.set != hs || hn3.event != "one" { | ||||
| 		t.Errorf("Third node for 'one' not created correctly") | ||||
| 	} | ||||
| 	if hn1.prev != nil || hn1.next != hn2 || | ||||
| 		hn2.prev != hn1 || hn2.next != hn3 || | ||||
| 		hn3.prev != hn2 || hn3.next != nil { | ||||
| 		t.Errorf("Nodes for 'one' not linked correctly.") | ||||
| 	} | ||||
| 	if hl.start != hn1 || hl.end != hn3 { | ||||
| 		t.Errorf("Node not appended to 'one' list correctly.") | ||||
| 	if hl.Len() != 3 { | ||||
| 		t.Errorf("List doesn't contain third 'one' after add().") | ||||
| 	} | ||||
| 
 | ||||
| 	// And finally a fourth one! | ||||
| 	hn4 := hs.add("one", HandlerFunc(f)).(*hNode) | ||||
| 	hn4 := hs.add("one", HandlerFunc(f)) | ||||
| 	if len(hs.set) != 1 { | ||||
| 		t.Errorf("Set contains more than 'one' list after add().") | ||||
| 	} | ||||
| 	if hn4.set != hs || hn4.event != "one" { | ||||
| 		t.Errorf("Fourth node for 'one' not created correctly.") | ||||
| 	} | ||||
| 	if hn1.prev != nil || hn1.next != hn2 || | ||||
| 		hn2.prev != hn1 || hn2.next != hn3 || | ||||
| 		hn3.prev != hn2 || hn3.next != hn4 || | ||||
| 		hn4.prev != hn3 || hn4.next != nil { | ||||
| 		t.Errorf("Nodes for 'one' not linked correctly.") | ||||
| 	} | ||||
| 	if hl.start != hn1 || hl.end != hn4 { | ||||
| 		t.Errorf("Node not appended to 'one' list correctly.") | ||||
| 	if hl.Len() != 4 { | ||||
| 		t.Errorf("List doesn't contain fourth 'one' after add().") | ||||
| 	} | ||||
| 
 | ||||
| 	// Dispatch should result in 4 additions. | ||||
|  | @ -94,16 +68,8 @@ func TestHandlerSet(t *testing.T) { | |||
| 	if len(hs.set) != 1 { | ||||
| 		t.Errorf("Set list count changed after remove().") | ||||
| 	} | ||||
| 	if hn3.set != nil || hn3.prev != nil || hn3.next != nil { | ||||
| 		t.Errorf("Third node for 'one' not removed correctly.") | ||||
| 	} | ||||
| 	if hn1.prev != nil || hn1.next != hn2 || | ||||
| 		hn2.prev != hn1 || hn2.next != hn4 || | ||||
| 		hn4.prev != hn2 || hn4.next != nil { | ||||
| 		t.Errorf("Third node for 'one' not unlinked correctly.") | ||||
| 	} | ||||
| 	if hl.start != hn1 || hl.end != hn4 { | ||||
| 		t.Errorf("Third node for 'one' changed list pointers.") | ||||
| 	if hl.Len() != 3 { | ||||
| 		t.Errorf("Third 'one' not removed correctly.") | ||||
| 	} | ||||
| 
 | ||||
| 	// Dispatch should result in 3 additions. | ||||
|  | @ -114,18 +80,12 @@ func TestHandlerSet(t *testing.T) { | |||
| 	} | ||||
| 
 | ||||
| 	// Remove node 1. | ||||
| 	hs.remove(hn1) | ||||
| 	hn1.Remove() | ||||
| 	if len(hs.set) != 1 { | ||||
| 		t.Errorf("Set list count changed after remove().") | ||||
| 	} | ||||
| 	if hn1.set != nil || hn1.prev != nil || hn1.next != nil { | ||||
| 		t.Errorf("First node for 'one' not removed correctly.") | ||||
| 	} | ||||
| 	if hn2.prev != nil || hn2.next != hn4 || hn4.prev != hn2 || hn4.next != nil { | ||||
| 		t.Errorf("First node for 'one' not unlinked correctly.") | ||||
| 	} | ||||
| 	if hl.start != hn2 || hl.end != hn4 { | ||||
| 		t.Errorf("First node for 'one' didn't change list pointers.") | ||||
| 	if hl.Len() != 2 { | ||||
| 		t.Errorf("First 'one' not removed correctly.") | ||||
| 	} | ||||
| 
 | ||||
| 	// Dispatch should result in 2 additions. | ||||
|  | @ -140,14 +100,8 @@ func TestHandlerSet(t *testing.T) { | |||
| 	if len(hs.set) != 1 { | ||||
| 		t.Errorf("Set list count changed after remove().") | ||||
| 	} | ||||
| 	if hn4.set != nil || hn4.prev != nil || hn4.next != nil { | ||||
| 		t.Errorf("Fourth node for 'one' not removed correctly.") | ||||
| 	} | ||||
| 	if hn2.prev != nil || hn2.next != nil { | ||||
| 		t.Errorf("Fourth node for 'one' not unlinked correctly.") | ||||
| 	} | ||||
| 	if hl.start != hn2 || hl.end != hn2 { | ||||
| 		t.Errorf("Fourth node for 'one' didn't change list pointers.") | ||||
| 	if hl.Len() != 1 { | ||||
| 		t.Errorf("Fourth 'one' not removed correctly.") | ||||
| 	} | ||||
| 
 | ||||
| 	// Dispatch should result in 1 addition. | ||||
|  | @ -158,16 +112,10 @@ func TestHandlerSet(t *testing.T) { | |||
| 	} | ||||
| 
 | ||||
| 	// Remove node 2. | ||||
| 	hs.remove(hn2) | ||||
| 	hn2.Remove() | ||||
| 	if len(hs.set) != 0 { | ||||
| 		t.Errorf("Removing last node in 'one' didn't remove list.") | ||||
| 	} | ||||
| 	if hn2.set != nil || hn2.prev != nil || hn2.next != nil { | ||||
| 		t.Errorf("Second node for 'one' not removed correctly.") | ||||
| 	} | ||||
| 	if hl.start != nil || hl.end != nil { | ||||
| 		t.Errorf("Second node for 'one' didn't change list pointers.") | ||||
| 	} | ||||
| 
 | ||||
| 	// Dispatch should result in NO additions. | ||||
| 	hs.dispatch(nil, &Line{Cmd: "One"}) | ||||
|  | @ -178,52 +126,43 @@ func TestHandlerSet(t *testing.T) { | |||
| } | ||||
| 
 | ||||
| func TestCommandSet(t *testing.T) { | ||||
| 	cs := commandSet() | ||||
| 	if len(cs.set) != 0 { | ||||
| 		t.Errorf("New set contains things!") | ||||
| 	cl := newCommandList() | ||||
| 	if cl.list.Len() != 0 { | ||||
| 		t.Errorf("New list contains things!") | ||||
| 	} | ||||
| 
 | ||||
| 	c := &command{ | ||||
| 		fn:   func(c *Conn, l *Line) {}, | ||||
| 		help: "wtf?", | ||||
| 	cn1 := cl.add("one", HandlerFunc(func(c *Conn, l *Line) {}), 0) | ||||
| 	if cl.list.Len() != 1 { | ||||
| 		t.Errorf("Command 'one' not added to list correctly.") | ||||
| 	} | ||||
| 
 | ||||
| 	cn1 := cs.add("ONE", c).(*cNode) | ||||
| 	if _, ok := cs.set["one"]; !ok || cn1.set != cs || cn1.prefix != "one" { | ||||
| 		t.Errorf("Command 'one' not added to set correctly.") | ||||
| 	} | ||||
| 
 | ||||
| 	if fail := cs.add("one", c); fail != nil { | ||||
| 		t.Errorf("Adding a second 'one' command did not fail as expected.") | ||||
| 	} | ||||
| 
 | ||||
| 	cn2 := cs.add("One Two", c).(*cNode) | ||||
| 	if _, ok := cs.set["one two"]; !ok || cn2.set != cs || cn2.prefix != "one two" { | ||||
| 	cn2 := cl.add("one two", HandlerFunc(func(c *Conn, l *Line) {}), 0) | ||||
| 	if cl.list.Len() != 2 { | ||||
| 		t.Errorf("Command 'one two' not added to set correctly.") | ||||
| 	} | ||||
| 
 | ||||
| 	if c, l := cs.match("foo"); c != nil || l != 0 { | ||||
| 	if c := cl.match("foo"); c != nil { | ||||
| 		t.Errorf("Matched 'foo' when we shouldn't.") | ||||
| 	} | ||||
| 	if c, l := cs.match("one"); c.(*cNode) != cn1 || l != 3 { | ||||
| 		t.Errorf("Didn't match 'one' when we should have.") | ||||
| 	if c := cl.match("one"); c == nil { | ||||
| 		t.Errorf("Didn't match when we should have.") | ||||
| 	} | ||||
| 	if c, l := cs.match("one two three"); c.(*cNode) != cn2 || l != 7 { | ||||
| 		t.Errorf("Didn't match 'one two' when we should have.") | ||||
| 	if c := cl.match("one two three"); c == nil { | ||||
| 		t.Errorf("Didn't match when we should have.") | ||||
| 	} | ||||
| 
 | ||||
| 	cs.remove(cn2) | ||||
| 	if _, ok := cs.set["one two"]; ok || cn2.set != nil { | ||||
| 	cn2.Remove() | ||||
| 	if cl.list.Len() != 1 { | ||||
| 		t.Errorf("Command 'one two' not removed correctly.") | ||||
| 	} | ||||
| 	if c, l := cs.match("one two three"); c.(*cNode) != cn1 || l != 3 { | ||||
| 		t.Errorf("Didn't match 'one' when we should have.") | ||||
| 	if c := cl.match("one two three"); c == nil { | ||||
| 		t.Errorf("Didn't match when we should have.") | ||||
| 	} | ||||
| 	cn1.Remove() | ||||
| 	if _, ok := cs.set["one"]; ok || cn1.set != nil { | ||||
| 		t.Errorf("Command 'one' not removed correctly.") | ||||
| 	if cl.list.Len() != 0 { | ||||
| 		t.Errorf("Command 'one two' not removed correctly.") | ||||
| 	} | ||||
| 	if c, l := cs.match("one two three"); c != nil || l != 0 { | ||||
| 		t.Errorf("Matched 'one' when we shouldn't have.") | ||||
| 	if c := cl.match("one two three"); c != nil { | ||||
| 		t.Errorf("Matched 'one' when we shouldn't.") | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -97,5 +97,23 @@ func (conn *Conn) h_NICK(line *Line) { | |||
| 
 | ||||
| // Handle PRIVMSGs that trigger Commands | ||||
| func (conn *Conn) h_PRIVMSG(line *Line) { | ||||
| 	conn.command(line) | ||||
| 	text := line.Message() | ||||
| 	if conn.CommandStripNick && strings.HasPrefix(text, conn.Me.Nick) { | ||||
| 		// Look for '^${nick}[:;>,-]? ' | ||||
| 		l := len(conn.Me.Nick) | ||||
| 		switch text[l] { | ||||
| 		case ':', ';', '>', ',', '-': | ||||
| 			l++ | ||||
| 		} | ||||
| 		if text[l] == ' ' { | ||||
| 			text = strings.TrimSpace(text[l:]) | ||||
| 		} | ||||
| 		line = line.Copy() | ||||
| 		line.Args[1] = text | ||||
| 	} | ||||
| 	cmd := conn.command(line) | ||||
| 	if cmd == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	cmd.Handle(conn, line) | ||||
| } | ||||
|  |  | |||
|  | @ -146,7 +146,9 @@ func TestPRIVMSG(t *testing.T) { | |||
| 	f := func(conn *Conn, line *Line) { | ||||
| 		conn.Privmsg(line.Args[0], line.Args[1]) | ||||
| 	} | ||||
| 	c.CommandFunc("prefix", f, "") | ||||
| 	// Test legacy simpleCommands, with out the !. | ||||
| 	SimpleCommandRegex = `^%v(\s|$)` | ||||
| 	c.SimpleCommandFunc("prefix", f) | ||||
| 
 | ||||
| 	// CommandStripNick and CommandStripPrefix are both false to begin | ||||
| 	c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :prefix bar")) | ||||
|  | @ -163,7 +165,7 @@ func TestPRIVMSG(t *testing.T) { | |||
| 	c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :test: prefix bar")) | ||||
| 	s.nc.Expect("PRIVMSG #foo :prefix bar") | ||||
| 
 | ||||
| 	c.CommandStripPrefix = true | ||||
| 	c.SimpleCommandStripPrefix = true | ||||
| 	c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :prefix bar")) | ||||
| 	s.nc.Expect("PRIVMSG #foo :bar") | ||||
| 	c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :test: prefix bar")) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue