From 4cd3831e92f8882a85c48d2ad2ca0d07bb42dcab Mon Sep 17 00:00:00 2001 From: Alex Bramley Date: Wed, 27 Feb 2013 20:23:24 +0000 Subject: [PATCH] Remove Commands from core goirc. This dictates too much about how people might want to parse and act upon information from PRIVMSGs, and thus should be an optional thing. --- client/connection.go | 7 +-- client/dispatch.go | 98 ----------------------------------------- client/dispatch_test.go | 51 --------------------- client/handlers.go | 34 -------------- client/handlers_test.go | 52 ---------------------- 5 files changed, 1 insertion(+), 241 deletions(-) diff --git a/client/connection.go b/client/connection.go index 30be2b9..89a631a 100644 --- a/client/connection.go +++ b/client/connection.go @@ -20,9 +20,8 @@ type Conn struct { // Contains parameters that people can tweak to change client behaviour. cfg *Config - // Handlers and Commands + // Handlers handlers *hSet - commands *cSet // State tracker for nicks and channels st state.Tracker @@ -61,9 +60,6 @@ type Config struct { // Client->server ping frequency, in seconds. Defaults to 3m. PingFreq time.Duration - // Controls what is stripped from line.Args[1] for Commands - CommandStripNick, CommandStripPrefix bool - // Set this to true to disable flood protection and false to re-enable Flood bool @@ -113,7 +109,6 @@ func Client(cfg *Config) (*Conn, error) { cLoop: make(chan bool), cPing: make(chan bool), handlers: handlerSet(), - commands: commandSet(), stRemovers: make([]Remover, 0, len(stHandlers)), lastsent: time.Now(), } diff --git a/client/dispatch.go b/client/dispatch.go index dd73865..b19d474 100644 --- a/client/dispatch.go +++ b/client/dispatch.go @@ -113,92 +113,6 @@ func (hs *hSet) dispatch(conn *Conn, line *Line) { } } -// An IRC command looks like this: -type Command interface { - Execute(*Conn, *Line) - Help() string -} - -type command struct { - fn HandlerFunc - help string -} - -func (c *command) Execute(conn *Conn, line *Line) { - c.fn(conn, line) -} - -func (c *command) Help() string { - return c.help -} - -type cNode struct { - cmd Command - set *cSet - prefix string -} - -func (cn *cNode) Execute(conn *Conn, line *Line) { - cn.cmd.Execute(conn, line) -} - -func (cn *cNode) Help() string { - return cn.cmd.Help() -} - -func (cn *cNode) Remove() { - cn.set.remove(cn) -} - -type cSet struct { - set map[string]*cNode - sync.RWMutex -} - -func commandSet() *cSet { - return &cSet{set: make(map[string]*cNode)} -} - -func (cs *cSet) add(pf string, c Command) Remover { - cs.Lock() - defer cs.Unlock() - pf = strings.ToLower(pf) - if _, ok := cs.set[pf]; ok { - logging.Error("Command prefix '%s' already registered.", pf) - return nil - } - cn := &cNode{ - cmd: c, - set: cs, - prefix: pf, - } - cs.set[pf] = cn - return cn -} - -func (cs *cSet) remove(cn *cNode) { - cs.Lock() - defer cs.Unlock() - delete(cs.set, cn.prefix) - cn.set = nil -} - -func (cs *cSet) match(txt string) (final Command, prefixlen int) { - cs.RLock() - defer cs.RUnlock() - txt = strings.ToLower(txt) - for prefix, cmd := range cs.set { - if !strings.HasPrefix(txt, prefix) { - continue - } - if final == nil || len(prefix) > prefixlen { - prefixlen = len(prefix) - final = cmd - } - } - return -} - // Handlers are triggered on incoming Lines from the server, with the handler // "name" being equivalent to Line.Cmd. Read the RFCs for details on what // replies could come from the server. They'll generally be things like @@ -213,18 +127,6 @@ func (conn *Conn) HandleFunc(name string, hf HandlerFunc) Remover { return conn.Handle(name, hf) } -func (conn *Conn) Command(prefix string, c Command) Remover { - return conn.commands.add(prefix, c) -} - -func (conn *Conn) CommandFunc(prefix string, hf HandlerFunc, help string) Remover { - return conn.Command(prefix, &command{hf, help}) -} - func (conn *Conn) dispatch(line *Line) { conn.handlers.dispatch(conn, line) } - -func (conn *Conn) cmdMatch(txt string) (Command, int) { - return conn.commands.match(txt) -} diff --git a/client/dispatch_test.go b/client/dispatch_test.go index 84b9e54..cba5893 100644 --- a/client/dispatch_test.go +++ b/client/dispatch_test.go @@ -176,54 +176,3 @@ func TestHandlerSet(t *testing.T) { t.Errorf("Our handler was called?") } } - -func TestCommandSet(t *testing.T) { - cs := commandSet() - if len(cs.set) != 0 { - t.Errorf("New set contains things!") - } - - c := &command{ - fn: func(c *Conn, l *Line) {}, - help: "wtf?", - } - - 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" { - t.Errorf("Command 'one two' not added to set correctly.") - } - - if c, l := cs.match("foo"); c != nil || l != 0 { - 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, l := cs.match("one two three"); c.(*cNode) != cn2 || l != 7 { - t.Errorf("Didn't match 'one two' when we should have.") - } - - cs.remove(cn2) - if _, ok := cs.set["one two"]; ok || cn2.set != nil { - 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.") - } - cn1.Remove() - if _, ok := cs.set["one"]; ok || cn1.set != nil { - t.Errorf("Command 'one' not removed correctly.") - } - if c, l := cs.match("one two three"); c != nil || l != 0 { - t.Errorf("Matched 'one' when we shouldn't have.") - } -} diff --git a/client/handlers.go b/client/handlers.go index 4efea47..aadd5d7 100644 --- a/client/handlers.go +++ b/client/handlers.go @@ -99,37 +99,3 @@ func (conn *Conn) h_NICK(line *Line) { conn.cfg.Me.Nick = line.Args[0] } } - -// Handle PRIVMSGs that trigger Commands -func (conn *Conn) h_PRIVMSG(line *Line) { - txt := line.Args[1] - if conn.cfg.CommandStripNick && strings.HasPrefix(txt, conn.cfg.Me.Nick) { - // Look for '^${nick}[:;>,-]? ' - l := len(conn.cfg.Me.Nick) - switch txt[l] { - case ':', ';', '>', ',', '-': - l++ - } - if txt[l] == ' ' { - txt = strings.TrimSpace(txt[l:]) - } - } - cmd, l := conn.cmdMatch(txt) - if cmd == nil { - return - } - if conn.cfg.CommandStripPrefix { - txt = strings.TrimSpace(txt[l:]) - } - if txt != line.Args[1] { - line = line.Copy() - line.Args[1] = txt - } - cmd.Execute(conn, line) -} - -func (conn *Conn) c_HELP(line *Line) { - if cmd, _ := conn.cmdMatch(line.Args[1]); cmd != nil { - conn.Privmsg(line.Args[0], cmd.Help()) - } -} diff --git a/client/handlers_test.go b/client/handlers_test.go index 147f7dd..fb91dad 100644 --- a/client/handlers_test.go +++ b/client/handlers_test.go @@ -2,7 +2,6 @@ package client import ( "code.google.com/p/gomock/gomock" - "fmt" "github.com/fluffle/goirc/state" "testing" "time" @@ -159,57 +158,6 @@ func TestCTCP(t *testing.T) { c.h_CTCP(parseLine(":blah!moo@cows.com PRIVMSG test :\001UNKNOWN ctcp\001")) } -func TestPRIVMSG(t *testing.T) { - c, s := setUp(t) - defer s.tearDown() - - f := func(conn *Conn, line *Line) { - conn.Privmsg(line.Args[0], line.Args[1]) - } - c.CommandFunc("prefix", f, "") - - // CommandStripNick and CommandStripPrefix are both false to begin - c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :prefix bar")) - s.nc.Expect("PRIVMSG #foo :prefix bar") - // If we're not stripping off the nick, the prefix won't match. - // This might be considered a bug, but then the library currently has a - // poor understanding of the concept of "being addressed". - c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :test: prefix bar")) - s.nc.ExpectNothing() - - c.cfg.CommandStripNick = true - c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :prefix bar")) - s.nc.Expect("PRIVMSG #foo :prefix bar") - c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :test: prefix bar")) - s.nc.Expect("PRIVMSG #foo :prefix bar") - - c.cfg.CommandStripPrefix = 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")) - s.nc.Expect("PRIVMSG #foo :bar") - - c.cfg.CommandStripNick = false - 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")) - s.nc.ExpectNothing() - - // Check the various nick addressing notations that are supported. - c.cfg.CommandStripNick = true - for _, addr := range []string{":", ";", ",", ">", "-", ""} { - c.h_PRIVMSG(parseLine(fmt.Sprintf( - ":blah!moo@cows.com PRIVMSG #foo :test%s prefix bar", addr))) - s.nc.Expect("PRIVMSG #foo :bar") - c.h_PRIVMSG(parseLine(fmt.Sprintf( - ":blah!moo@cows.com PRIVMSG #foo :test%sprefix bar", addr))) - s.nc.ExpectNothing() - } - c.h_PRIVMSG(parseLine(":blah!moo@cows.com PRIVMSG #foo :test! prefix bar")) - s.nc.ExpectNothing() - -} - // Test the handler for JOIN messages func TestJOIN(t *testing.T) { c, s := setUp(t)