We need some way of making a plugin "greedy" or maybe just ignore !command messages.
Plugin conflicts #76
It seems this effects many plugins not just beertime and 8ball. As discussed on IRC :)
I have a solution where an additional attribute can be included in the Info object. The attribute will reflect if a plugin is (going to be) called. On an empty Info object (which you use to register events) this will default to False, so by default events are not called if a plugin is called. This seems to be the most megbot-like solution, we're already using the Info object to tell events when to trigger or not.
The obvious problem is how do you handle it when you want both to be called when a plugin is called and when it isn't. It seems to me there are a few solutions to this:
- Register your event twice: once with
Info.triggered = False(the default) and one withInfo.triggered = True - Allow attributes to take multiple values via tuples e.g.
Info.triggered = (True, False)the downside to this is some attributes such asInfo.nickmaskare tuples, it's ambiguous and inconsistent. 👎 - I think my preference would be allow them to take a callable which returns if it matches, example of this with the seen plugin below:
def init(connection):
eventID = 'seenEvent'
info = connection.libraries["IRCObjects"].Info()
# this will peform an event on privmsg.
info.action = "PRIVMSG"
info.triggered = lambda t: True # Always match on this value.
event = connection.core["Corehandler"].IRCEvent(info, on_PRIVMSG, eventID)
connection.handler.register_event(event)
With this solution in place: beertime wouldn't conflict with anything as it'd leave this as default, nor would reply. The scene plugin can be made to always log as it does now with a small additional change. We also keep the idea of Info being created to reflect when you want your event called.
That means attaching plugin state onto the incoming Info object (otherwise how is the callable on Info.triggered?). I don't like that at all.
My personal preference would be if event handlers returned something, perhaps a truthy value:
def on_PRIV(conn, info):
store.add_message(info) # do something or other
# implicit return None, which is falsey
def on_cmd(conn, info):
who, what, when = store.get_user(info)
info.channel.send("%s said %s on %s" % (who, what, when))
return True
def init(connection):
# register these event, order is important
## etc. etc. etc.
Then whatever is iterating over can do something like:
for callback in list_of_matching_callbacks:
result = callback(conn, info)
if result:
break
No due date set.
No dependencies set.
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?