diff --git a/README.md b/README.md index 5f22864..7f3d53f 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ Synopsis: // Add handlers to do things here! // e.g. join a channel on connect. - c.AddHandler("connected", + c.AddHandler(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { conn.Join("#channel") }) // And a signal on disconnect quit := make(chan bool) - c.AddHandler("disconnected", + c.AddHandler(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) // Tell client to connect diff --git a/client.go b/client.go index cb8d02f..c0b4368 100644 --- a/client.go +++ b/client.go @@ -1,11 +1,11 @@ package main import ( - irc "github.com/fluffle/goirc/client" + "bufio" "flag" "fmt" + irc "github.com/fluffle/goirc/client" "os" - "bufio" "strings" ) @@ -18,12 +18,12 @@ func main() { // create new IRC connection c := irc.SimpleClient("GoTest", "gotest") c.EnableStateTracking() - c.AddHandler("connected", + c.AddHandler(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { conn.Join(*channel) }) // Set up a handler to notify of disconnect events. quit := make(chan bool) - c.AddHandler("disconnected", + c.AddHandler(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) // set up a goroutine to read commands from stdin @@ -36,6 +36,8 @@ func main() { if err != nil { // wha?, maybe ctrl-D... close(in) + reallyquit = true + c.Quit("") break } // no point in sending empty lines down the channel diff --git a/client/connection.go b/client/connection.go index 0b3f3ad..0bb9255 100644 --- a/client/connection.go +++ b/client/connection.go @@ -16,9 +16,10 @@ import ( // An IRC connection is represented by this struct. type Conn struct { // Connection Hostname and Nickname - Host string - Me *state.Nick - Network string + Host string + Me *state.Nick + Network string + password string // Replaceable function to customise the 433 handler's new nick NewNick func(string) string @@ -60,7 +61,7 @@ type Conn struct { Flood bool // Internal counters for flood protection - badness time.Duration + badness time.Duration lastsent time.Time } @@ -177,14 +178,13 @@ func (conn *Conn) Connect(host string, pass ...string) error { } } conn.Host = host + if len(pass) > 0 { + conn.password = pass[0] + } else { + conn.password = "" + } conn.Connected = true conn.postConnect() - - if len(pass) > 0 { - conn.Pass(pass[0]) - } - conn.Nick(conn.Me.Nick) - conn.User(conn.Me.Ident, conn.Me.Name) return nil } @@ -202,6 +202,7 @@ func (conn *Conn) postConnect() { go func() { <-conn.cPing }() } go conn.runLoop() + conn.ED.Dispatch(INIT, conn, &Line{}) } // copied from http.client for great justice @@ -319,7 +320,7 @@ func (conn *Conn) shutdown() { // as calling sock.Close() will cause recv() to recieve EOF in readstring() if conn.Connected { conn.l.Info("irc.shutdown(): Disconnected from server.") - conn.ED.Dispatch("disconnected", conn, &Line{}) + conn.ED.Dispatch(DISCONNECTED, conn, &Line{}) conn.Connected = false conn.sock.Close() conn.cSend <- true diff --git a/client/handlers.go b/client/handlers.go index 72a72c6..d4a3c9d 100644 --- a/client/handlers.go +++ b/client/handlers.go @@ -8,8 +8,15 @@ import ( "strings" ) +// Consts for unnamed events. +const ( + INIT = "init" + CONNECTED = "connected" + DISCONNECTED = "disconnected" +) + // An IRC handler looks like this: -type IRCHandler func(*Conn, *Line) +type Handler func(*Conn, *Line) // AddHandler() adds an event handler for a specific IRC command. // @@ -19,14 +26,14 @@ 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) event.Handler { +func (conn *Conn) AddHandler(name string, f Handler) event.Handler { h := NewHandler(f) conn.ER.AddHandler(h, name) return h } // Wrap f in an anonymous unboxing function -func NewHandler(f IRCHandler) event.Handler { +func NewHandler(f Handler) event.Handler { return event.NewHandler(func(ev ...interface{}) { f(ev[0].(*Conn), ev[1].(*Line)) }) @@ -34,8 +41,10 @@ func NewHandler(f IRCHandler) event.Handler { // sets up the internal event handlers to do essential IRC protocol things var intHandlers map[string]event.Handler + func init() { intHandlers = make(map[string]event.Handler) + intHandlers[INIT] = NewHandler((*Conn).h_init) intHandlers["001"] = NewHandler((*Conn).h_001) intHandlers["433"] = NewHandler((*Conn).h_433) intHandlers["CTCP"] = NewHandler((*Conn).h_CTCP) @@ -49,6 +58,15 @@ func (conn *Conn) addIntHandlers() { } } +// Password/User/Nick broadcast on connection. +func (conn *Conn) h_init(line *Line) { + if conn.password != "" { + conn.Pass(conn.password) + } + conn.Nick(conn.Me.Nick) + conn.User(conn.Me.Ident, conn.Me.Name) +} + // Basic ping/pong handler func (conn *Conn) h_PING(line *Line) { conn.Raw("PONG :" + line.Args[0]) @@ -57,7 +75,7 @@ func (conn *Conn) h_PING(line *Line) { // Handler to trigger a "CONNECTED" event on receipt of numeric 001 func (conn *Conn) h_001(line *Line) { // we're connected! - conn.ED.Dispatch("connected", conn, line) + conn.ED.Dispatch(CONNECTED, conn, line) // and we're being given our hostname (from the server's perspective) t := line.Args[len(line.Args)-1] if idx := strings.LastIndex(t, " "); idx != -1 {