cinchrb / cinch

The IRC Bot Building Framework
http://www.rubydoc.info/gems/cinch
MIT License
1k stars 180 forks source link

fall-through reply #60

Open ghost opened 12 years ago

ghost commented 12 years ago

When the bot receives a message that no plugin has responded to, it would be great if there was a way to supply a response message.

blowback commented 12 years ago

In a similar vein, it would be nice to be able to group plugins together, so that they can all match the same message, but are called in order until somebody handles it. For example, i might have 3 plugins, PluginA, PluginB, PluginC that all handle !lookup <word>: PluginA is called, if it doesn't handle it PluginB is called, if B doesn't handle it, PluginC is called.

I have been experimenting with a "PartyLine" plugin, which maintains its own PluginList and does the round-robin calling of its child plugins as described above. I'm handling the "did PluginA respond?" issue by passing a PartyLineMessage which derives from Message.

This works reasonably well, the main advantage is that a Plugin's implementation doesn't know or care whether it's a real plugin or a PartyLine plugin. The disadvantage is that I can only judge if a plugin has handled the response based on whether it called m.reply() or not, and if cinch in future provides any builtin support for dynamic plugin management it will not see the PartyLine plugins, as they are on a separate list. For the time being tho, it serves my purposes well enough.

dominikh commented 12 years ago

This is technically not possible, because all three plugins will be executed in parallel.

What is currently possible is to group matches in a single plugin together. Of those, only the first matching one will execute. Of course that won't allow you to first execute the handler and then decide if it is suitable or not. This is generally a problem not solvable in Cinch because of the threaded architecture.

It would be more advisable to have one dispatcher plugin that determines what class to use for the lookup, that is make the lookup classes independent from the plugin infrastructure itself.

blowback commented 12 years ago

Sorry, it seems I'm not explaining myself very well. I'm not talking about achieving this with the current version of cinch, it is obvious that it is impossible to make consecutive decisions from a bunch of processes that execute concurrently.

What I'm talking about is some future cinch (which is what I assumed the 'feature' tag indicated, perhaps erronously) where this might be possible.

I think it would be extremely cool to be able to take a plugin and either have it behave as plugins behave now, or to behave as one of these first-come-first-served groups, without any change whatsoever to the plugin code.

As a proof of concept have a look at this commit if you can spare the time (it is not large).

Here you can see that I have three Plugins, which can behave as regular cinch plugins, no problem. Or, by inserting a PartyLine plugin as a proxy, they are called in turn.

This has required some changes to cinch, but you can see that they're relatively minor: I changed handler.rb and the various wrappers to be able to return a value, and handler_list.rb to take a 'synchronous' flag and change it's behaviour slightly if synchronous is TRUE.

I like the 'intermediate proxy plugin' approach because it makes the grouping of the subordinate plugins explicit and simple. And it requires relatively few changes to cinch stuff. From a plugin writer's perspective, they only have to be mindful of their return values.

I think to implement this in the cinch core instead in some way would be problematic, as you'd have to deal with the semantics of grouping these plugins together, especially tricky as we already have 'group' meaning something else....it would all end up very confusing and probably not worth the effort.

The only other issue I can see is that PartyLine fakes up the event it uses to call its subordinate plugins, as it doesn't know what the current event was. There's probably a better/more flexible way of dealing with that.

Also I haven't tested this; I've no idea if timers, listeners, ctcp etc. will give it indigestion. So far so good, and I plan to use it in a real bot so it will be getting some exercise.

So there we go. It's possible I'm the only person in the world who wants this behaviour, which is fine, but I'm hoping the proxy_plugin + minor_cinch_mods tickles your tastebuds!

It is a testament to the flexibility of cinch that I am able to make this work at all, with so few changes!