// InvokeInit stops at the first error // If plugins is nil, all plugins are inited. // Otherwise, only the listed plugins are inited. func InvokeInit(plugins []string, config map[string]map[string]interface{}) error { pluginState.Lock() defer pluginState.Unlock() if pluginState.State != StatePreInit { panic("InvokeInit called after init") } var pluginMap map[string]bool if plugins != nil { pluginMap = make(map[string]bool, len(plugins)) pluginMap[""] = true // always load unnamed plugins, they're for support for _, name := range plugins { pluginMap[name] = true } } pluginState.State = StatePostInit registry = callback.NewRegistry(callback.DispatchSerial) for _, plugin := range pluginState.Plugins { if pluginMap != nil && !pluginMap[plugin.Name] { continue } callbacks := plugin.Callbacks if callbacks.Init != nil { if err := callbacks.Init(registry, config[plugin.Name]); err != nil { return err } } plugin.inited = true } return nil }
// Connect initiates a connection to an IRC server identified by the Config. // It returns once the connection has been established. // If a connection could not be established, an error is returned. func Connect(config Config) (SafeConn, error) { if config.Init == nil { return nil, errors.New("Config needs an Init function") } port := config.Port if port == 0 { if config.SSL { port = 6697 } else { port = 6667 } } addr := net.JoinHostPort(config.Host, strconv.FormatUint(uint64(port), 10)) writer, reader := make(chan string), make(chan string) writeErr, readErr := make(chan error, 1), make(chan error, 1) invoker := make(chan func(*Conn)) conn := &Conn{ me: User{ Nick: config.Nick, User: config.User, }, stateRegistry: callback.NewRegistry(callback.DispatchSerial), nickInUse: config.NickInUse, writer: writer, reader: reader, writeErr: writeErr, readErr: readErr, invoker: invoker, safeConnState: &safeConnState{ server: addr, registry: callback.NewRegistry(callback.DispatchSerial), }, } nc, err := dialServer(addr, config.Timeout, config.SSL, config.SSLConfig) if err != nil { return nil, err } conn.netconn = nc config.Init(conn) // set up the writer and reader before we call any callbacks go connWriter(nc, writer, writeErr, config.AllowFlood) go connReader(nc, reader, readErr) // also set up the invoker infinite queue queue := make(chan func(*Conn)) go invokerQueue(invoker, queue) // set up the safeConnState conn.safeConnState.Lock() conn.safeConnState.writer = conn.writer conn.safeConnState.invoker = queue conn.safeConnState.Unlock() // set up the pinger if config.PingInterval >= 0 { delta := config.PingInterval if delta == 0 { delta = 3 * time.Minute } go pinger(conn.SafeConn(), delta) } // dispatch the INIT callback conn.safeConnState.registry.Dispatch(INIT, conn) // set up our state handlers conn.setupStateHandlers() // fire off the login lines conn.logIn(config.RealName, config.Password) // and finally, start the main loop in a new goroutine go conn.runLoop() return conn.SafeConn(), nil }