func (h *Handler) removeUnstableClient(name ModuleName, err error) { // RPC call failed, module deemed unstable and is therefore removed // Signal a clean up to module rlog.Warn("Handler", "Removing "+string(name)+" [Module Client] due to RPC error: "+ err.Error()) err = h.SignalCleanup(name) if err != nil { rlog.Warn("Handler", string(name)+ " [Module Client] did not successfully clean up, it will still be removed.") } h.RemoveModule(name) h.signalRemove(name) }
// Limiter will rate limit inbound or outbound actions. If lim is Inlim, it will rate limit using // the inbound rate limiter. If lim is Outlim, it will limit using the outbound limiter. A chan is // is returned to the caller. It will be fulfilled when the rate limiter is able to act or when the // bot has quit. Therefore a caller should check the value, as a false indicates that the bot's // connection has been closed and no more inbound or outbound actions should be acted upon. func (b *Bot) Limiter(lim string) chan bool { ch := make(chan bool, 1) go func(ch chan bool) { var r *rate.Reservation if lim == Inlim { r = b.Inlim.Reserve() } else if lim == Outlim { r = b.Outlim.Reserve() } else { ch <- false } if !r.OK() { rlog.Warn("Bot", lim+" not able to act") } // If in case the delay wins over the quit, the handler will have appropriated measures. select { case <-time.After(r.Delay()): ch <- true case <-b.quit: ch <- false case <-b.Client.Quit(): ch <- false } }(ch) return ch }
// RplTopic will set the topic for a created channel func (l *Listeners) RplTopic(msg *irc.Message) { l.bot.Mu.Lock() name := msg.Params[1] topic := msg.Trailing channel, ok := l.bot.Channels[strings.ToLower(name)] if !ok { rlog.Warn("Bot", "Got RPL_TOPIC for a channel that hasn't been initialized yet") } else { channel.Topic = topic } l.bot.Mu.Unlock() }
// Register registers a module with the bot. With the given port number in the Ticket, the bot // creates a new rpc provider client connection to the module. The module is kept in the handler // for event dispatching and module management. func (b BotAPI) Register(t Ticket, result *string) error { rlog.Debug("Bot", "Starting registration for "+t.ModuleName+" [Module Client]") client, err := RpcCodecClientWithPort(t.Port) if err != nil { rlog.Error("Bot", "Could not establish an RPC client: "+err.Error()) return err } module := rpc.NewClientWithCodec(client) if module == nil { rlog.Warn("Bot", "Could not register:"+t.ModuleName) return errors.New("Failed to regsiter module") } b.bot.Handler.AddModule(ModuleName(strings.ToLower(t.ModuleName)), module) b.bot.Modules[strings.ToLower(t.ModuleName)].Registered = true rlog.Debug("Bot", "Registered "+t.ModuleName+" on port "+t.Port) return nil }
// RplNamreply will insert all users into the corresponding channel func (l *Listeners) RplNamreply(msg *irc.Message) { l.bot.Mu.Lock() defer l.bot.Mu.Unlock() channel, ok := l.bot.Channels[strings.ToLower(msg.Params[2])] users := strings.Split(strings.Trim(msg.Trailing, " "), " ") if !ok { rlog.Warn("Bot", "Got RPL_NAMREPLY for a channel that hasn't been initialized yet") return } for _, user := range users { var name, rank string if strings.ContainsAny(string(user[0]), "+ & ~ & @ & &") { name, rank = user[1:], string(user[0]) } else { name, rank = user, "" } channel.Users[name] = rank } }