func (p *helpPlugin) HandleMessage(msg *mup.Message) { if msg.BotText == "" || msg.Bang != "" && strings.HasPrefix(msg.Text, msg.Bang) { return } cmdname := schema.CommandName(msg.BotText) if cmdname != "" { infos, err := p.pluginsWith(cmdname, false) if err == nil && len(infos) == 0 { infos, err = p.pluginsWith(cmdname, true) if len(infos) > 0 { p.sendNotUsable(msg, &infos[0], "running", "") return } } if err != nil { p.plugger.Logf("Cannot list available commands: %v", err) p.plugger.Sendf(msg, "Cannot list available commands: %v", err) return } if len(infos) == 0 { p.sendNotKnown(msg, cmdname) return } addr := msg.Address() for _, info := range infos { for _, target := range info.Targets { if target.Contains(addr) { return } } } p.sendNotUsable(msg, &infos[0], "enabled", "here") } }
func (m *pluginManager) loop() error { defer m.die() if m.config.Plugins != nil && len(m.config.Plugins) == 0 { <-m.tomb.Dying() return nil } m.tomb.Go(m.tail) m.updateKnown() m.handleRefresh() var refresh <-chan time.Time if m.config.Refresh > 0 { ticker := time.NewTicker(m.config.Refresh) defer ticker.Stop() refresh = ticker.C } plugins := m.database.C("plugins") for { m.session.Refresh() select { case msg := <-m.incoming: if msg.Command == cmdPong { continue } cmdName := schema.CommandName(msg.BotText) for name, state := range m.plugins { if state.info.LastId >= msg.Id || state.plugger.Target(msg) == nil { continue } state.info.LastId = msg.Id state.handle(msg, cmdName) err := plugins.UpdateId(name, bson.D{{"$set", bson.D{{"lastid", msg.Id}}}}) if err != nil { logf("Cannot update last message id for plugin %q: %v", name, err) // TODO How to recover properly from this? } } case req := <-m.requests: switch req := req.(type) { case pluginRequestStop: return nil case pluginRequestRefresh: m.handleRefresh() close(req.done) default: panic("unknown request received by plugin manager") } case <-refresh: m.handleRefresh() } } return nil }
func (s *S) TestCommandParse(c *C) { for _, test := range parseTests { c.Logf("Processing command line: %q", test.text) name := schema.CommandName(test.text) cmd := commands.Command(name) if cmd == nil { c.Fatalf("Cannot find command %q", name) } opts, err := cmd.Parse(test.text) if test.error != "" { c.Assert(err, ErrorMatches, test.error) } else { c.Assert(err, IsNil) c.Assert(opts, DeepEquals, test.opts) } } }
// Sendf formats a PRIVMSG coming from "nick!~user@host" and delivers to the plugin // being tested for handling as a message, as a command, or both, depending on the // plugin specification and implementation. // // The formatted message may be prefixed by "[<target>@<account>,<option>] " to define // the channel or bot nick the message was addressed to, the account name it was // observed on, and a list of comma-separated options. All fields are optional, and // default to "[mup@test] ". The only supported option at the moment is "raw", which // causes the message text to be taken as a raw IRC protocol message. When providing // a target without an account the "@" may be omitted, and the comma may be omitted // if there are no options. // // Sendf always delivers the message to the plugin, irrespective of which targets // are currently setup, as it doesn't make sense to test the plugin with a message // that it cannot observe. func (t *PluginTester) Sendf(format string, args ...interface{}) { account, message := parseSendfText(fmt.Sprintf(format, args...)) msg := ParseIncoming(account, "mup", "!", message) t.state.handle(msg, schema.CommandName(msg.BotText)) }