diff --git a/client/connection.go b/client/connection.go index ef0a8e7..269c8c7 100644 --- a/client/connection.go +++ b/client/connection.go @@ -66,20 +66,31 @@ type Conn struct { // Creates a new IRC connection object, but doesn't connect to anything so // that you can add event handlers to it. See AddHandler() for details. -// Dependency injection is a bitch :-/ -func New(nick, user, name string, st bool, - r event.EventRegistry, l logging.Logger) *Conn { - if r == nil { - r = event.NewRegistry() +func SimpleClient(nick string, args ...string) *Conn { + r := event.NewRegistry() + l := logging.NewFromFlags() + ident := "goirc" + name := "Powered by GoIRC" + + if len(args) > 0 && args[0] != "" { + ident = args[0] } - if l == nil { - l = logging.NewFromFlags() + if len(args) > 1 && args[1] != "" { + name = args[1] + } + return Client(nick, ident, name, r, l) +} + +func Client(nick, ident, name string, + r event.EventRegistry, l logging.Logger) *Conn { + if r == nil || l == nil { + return nil } conn := &Conn{ ER: r, ED: r, l: l, - st: st, + st: false, in: make(chan *Line, 32), out: make(chan string, 32), cSend: make(chan bool), @@ -92,20 +103,35 @@ func New(nick, user, name string, st bool, lastsent: 0, } conn.addIntHandlers() - if st { - conn.ST = state.NewTracker(nick, l) - conn.Me = conn.ST.Me() - conn.addSTHandlers() - } else { - conn.Me = state.NewNick(nick, l) - } - conn.Me.Ident = user + conn.Me = state.NewNick(nick, l) + conn.Me.Ident = ident conn.Me.Name = name conn.initialise() return conn } +func (conn *Conn) EnableStateTracking() { + if !conn.st { + n := conn.Me + conn.ST = state.NewTracker(n.Nick, conn.l) + conn.Me = conn.ST.Me() + conn.Me.Ident = n.Ident + conn.Me.Name = n.Name + conn.addSTHandlers() + conn.st = true + } +} + +func (conn *Conn) DisableStateTracking() { + if conn.st { + conn.st = false + conn.delSTHandlers() + conn.ST.Wipe() + conn.ST = nil + } +} + // Per-connection state initialisation. func (conn *Conn) initialise() { conn.io = nil diff --git a/client/connection_test.go b/client/connection_test.go index 2dc09fd..7d3b852 100644 --- a/client/connection_test.go +++ b/client/connection_test.go @@ -1,6 +1,7 @@ package client import ( + "github.com/fluffle/goirc/event" "github.com/fluffle/goirc/logging" "github.com/fluffle/goirc/state" "gomock.googlecode.com/hg/gomock" @@ -20,9 +21,10 @@ type testState struct { func setUp(t *testing.T) (*Conn, *testState) { ctrl := gomock.NewController(t) st := state.NewMockStateTracker(ctrl) + r := event.NewRegistry() l := logging.NewMockLogger(ctrl) nc := MockNetConn(t) - c := New("test", "test", "Testing IRC", false, nil, l) + c := Client("test", "test", "Testing IRC", r, l) // We don't want to have to specify s.log.EXPECT().Debug() for all the // random crap that gets logged. This mocks it all out nicely. diff --git a/client/handlers.go b/client/handlers.go index 67fff07..f664941 100644 --- a/client/handlers.go +++ b/client/handlers.go @@ -19,8 +19,10 @@ type IRCHandler func(*Conn, *Line) // "PRIVMSG", "JOIN", etc. but all the numeric replies are left as ascii // strings of digits like "332" (mainly because I really didn't feel like // putting massive constant tables in). -func (conn *Conn) AddHandler(name string, f IRCHandler) { - conn.ER.AddHandler(name, NewHandler(f)) +func (conn *Conn) AddHandler(name string, f IRCHandler) event.Handler { + h := NewHandler(f) + conn.ER.AddHandler(h, name) + return h } // Wrap f in an anonymous unboxing function diff --git a/client/state_handlers.go b/client/state_handlers.go index 1ac1f2c..3da84dc 100644 --- a/client/state_handlers.go +++ b/client/state_handlers.go @@ -4,24 +4,39 @@ package client // to manage tracking state for an IRC connection import ( + "github.com/fluffle/goirc/event" "strings" ) -func (conn *Conn) addSTHandlers() { - conn.AddHandler("JOIN", (*Conn).h_JOIN) - conn.AddHandler("KICK", (*Conn).h_KICK) - conn.AddHandler("MODE", (*Conn).h_MODE) - conn.AddHandler("NICK", (*Conn).h_STNICK) - conn.AddHandler("PART", (*Conn).h_PART) - conn.AddHandler("QUIT", (*Conn).h_QUIT) - conn.AddHandler("TOPIC", (*Conn).h_TOPIC) +var stHandlers map[string]event.Handler - conn.AddHandler("311", (*Conn).h_311) - conn.AddHandler("324", (*Conn).h_324) - conn.AddHandler("332", (*Conn).h_332) - conn.AddHandler("352", (*Conn).h_352) - conn.AddHandler("353", (*Conn).h_353) - conn.AddHandler("671", (*Conn).h_671) +func init() { + stHandlers = make(map[string]event.Handler) + stHandlers["JOIN"] = NewHandler((*Conn).h_JOIN) + stHandlers["KICK"] = NewHandler((*Conn).h_KICK) + stHandlers["MODE"] = NewHandler((*Conn).h_MODE) + stHandlers["NICK"] = NewHandler((*Conn).h_STNICK) + stHandlers["PART"] = NewHandler((*Conn).h_PART) + stHandlers["QUIT"] = NewHandler((*Conn).h_QUIT) + stHandlers["TOPIC"] = NewHandler((*Conn).h_TOPIC) + stHandlers["311"] = NewHandler((*Conn).h_311) + stHandlers["324"] = NewHandler((*Conn).h_324) + stHandlers["332"] = NewHandler((*Conn).h_332) + stHandlers["352"] = NewHandler((*Conn).h_352) + stHandlers["353"] = NewHandler((*Conn).h_353) + stHandlers["671"] = NewHandler((*Conn).h_671) +} + +func (conn *Conn) addSTHandlers() { + for n, h := range stHandlers { + conn.ER.AddHandler(h, n) + } +} + +func (conn *Conn) delSTHandlers() { + for n, h := range stHandlers { + conn.ER.DelHandler(h, n) + } } // Handle NICK messages that need to update the state tracker