ircbot: attempt to bring recursion back
so initial tests suggest this is working well, but it's not exactly the clearest code, so let's call this a rough proof of concept of recursion in the bot
This commit is contained in:
parent
115e82f0fc
commit
5716e285b6
@ -2,6 +2,7 @@
|
||||
|
||||
import bisect
|
||||
import collections
|
||||
import copy
|
||||
import logging
|
||||
import re
|
||||
import ssl
|
||||
@ -98,6 +99,8 @@ class DrReactor(irc.client.Reactor):
|
||||
log.debug("EVENT: e[%s] s[%s] t[%s] a[%s]", event.type, event.source,
|
||||
event.target, event.arguments)
|
||||
|
||||
self.try_recursion(connection, event)
|
||||
|
||||
# only do aliasing for pubmsg/privmsg
|
||||
if event.type in ['pubmsg', 'privmsg']:
|
||||
what = event.arguments[0]
|
||||
@ -132,10 +135,138 @@ class DrReactor(irc.client.Reactor):
|
||||
self.handlers.get(event.type, [])
|
||||
)
|
||||
for handler in matching_handlers:
|
||||
log.debug(u"not-match")
|
||||
result = handler.callback(connection, event)
|
||||
if result == "NO MORE":
|
||||
return
|
||||
|
||||
def try_recursion(self, connection, event):
|
||||
"""Scan message for subcommands to execute and use as part of this command.
|
||||
|
||||
Upon seeing a line intended for this module, see if there are subcommands
|
||||
that we should do what is basically a text replacement on. The intent is to
|
||||
allow things like the following:
|
||||
|
||||
command arg1 [anothercommand arg1 arg2]
|
||||
|
||||
where the output of anothercommand is command's arg2..n.
|
||||
|
||||
Args:
|
||||
connection source connection
|
||||
event incoming event
|
||||
|
||||
"""
|
||||
|
||||
log.debug(u"RECURSING EVENT: e[%s] s[%s] t[%s] a[%s]", event.type, event.source,
|
||||
event.target, event.arguments)
|
||||
|
||||
try:
|
||||
# begin recursion search
|
||||
attempt = event.arguments[0]
|
||||
|
||||
log.debug(u"checking it against %s", attempt)
|
||||
|
||||
start_idx = attempt.find('[')
|
||||
subcmd = attempt[start_idx+1:]
|
||||
end_idx = subcmd.rfind(']')
|
||||
subcmd = subcmd[:end_idx]
|
||||
|
||||
if start_idx != -1 and end_idx != -1 and len(subcmd) > 0:
|
||||
log.debug(u"subcmd: %s", subcmd)
|
||||
|
||||
# found recursion candidate
|
||||
# copy the event and see if IT has recursion to do
|
||||
newevent = copy.deepcopy(event)
|
||||
newevent.arguments[0] = subcmd
|
||||
newevent._recursing = True
|
||||
|
||||
log.debug(u"new event copied")
|
||||
|
||||
self.try_recursion(connection, newevent)
|
||||
|
||||
# now that we have a string that has been
|
||||
# recursed all the way deeper into its text, see if any
|
||||
# modules can do something with it. this calls the same
|
||||
# event handlers in the same way as if this were a native
|
||||
# event.
|
||||
self.try_to_replace_event_text_with_module_text(connection, newevent)
|
||||
|
||||
# we have done all we can do with the sub-event. whatever
|
||||
# the text of that event now is, we should replace the parent
|
||||
# event's [] section with it.
|
||||
oldtext = event.arguments[0]
|
||||
newtext = oldtext.replace('['+subcmd+']', newevent.arguments[0])
|
||||
log.debug(u"oldtext: '%s' newtext: '%s'", oldtext, newtext)
|
||||
event.arguments[0] = newtext
|
||||
|
||||
# we have now resolved the []. recursion will unfold, replacing
|
||||
# it further and further, until we eventually get back to the
|
||||
# original irc event in _handle_event, which will do one
|
||||
# last search on the text.
|
||||
else:
|
||||
log.debug(u"no more recursion here")
|
||||
except IndexError:
|
||||
log.debug(u"no more recursion here")
|
||||
|
||||
def try_to_replace_event_text_with_module_text(self, connection, event):
|
||||
"""Do something very similar to _handle_event, but for recursion.
|
||||
|
||||
The intent here is that we replace [text] with whatever a module
|
||||
provides to us.
|
||||
|
||||
Args:
|
||||
connection source connection
|
||||
event incoming event
|
||||
|
||||
"""
|
||||
|
||||
replies = []
|
||||
|
||||
# only do aliasing for pubmsg/privmsg
|
||||
if event.type in ['pubmsg', 'privmsg']:
|
||||
what = event.arguments[0]
|
||||
log.debug(u"checking for (recursion) alias for %s", what)
|
||||
|
||||
for alias in Alias.objects.all():
|
||||
repl = alias.replace(what)
|
||||
if repl:
|
||||
# we found an alias for our given string, doing a replace
|
||||
event.arguments[0] = repl
|
||||
|
||||
with self.mutex:
|
||||
# doing regex version first as it has the potential to be more specific
|
||||
log.debug(u"checking (recursion) regex handlers for %s", event.type)
|
||||
matching_handlers = sorted(
|
||||
self.regex_handlers.get("all_events", []) +
|
||||
self.regex_handlers.get(event.type, [])
|
||||
)
|
||||
log.debug(u"got %d", len(matching_handlers))
|
||||
for handler in matching_handlers:
|
||||
log.debug(u"checking (recursion) %s vs. %s", handler, event.arguments)
|
||||
for line in event.arguments:
|
||||
match = re.search(handler.regex, line)
|
||||
if match:
|
||||
log.debug(u"match (recursion)!")
|
||||
result = handler.callback(connection, event, match)
|
||||
log.debug(u"result: %s", result)
|
||||
if result:
|
||||
log.debug(u"appending %s to replies", result)
|
||||
replies.append(result)
|
||||
|
||||
matching_handlers = sorted(
|
||||
self.handlers.get("all_events", []) +
|
||||
self.handlers.get(event.type, [])
|
||||
)
|
||||
for handler in matching_handlers:
|
||||
log.debug(u"not-match (recursion)")
|
||||
result = handler.callback(connection, event)
|
||||
log.debug(u"result: %s", result)
|
||||
if result:
|
||||
log.debug(u"appending %s to replies", result)
|
||||
replies.append(result)
|
||||
|
||||
if len(replies):
|
||||
event.arguments[0] = '\n'.join(replies)
|
||||
|
||||
|
||||
class IRCBot(irc.client.SimpleIRCClient):
|
||||
@ -514,10 +645,13 @@ class IRCBot(irc.client.SimpleIRCClient):
|
||||
"NO MORE" to stop other event handlers from acting.
|
||||
"""
|
||||
|
||||
log.debug(u"in reply for e[%s] r[%s]", event, replystr)
|
||||
replypath = ircbotlib.reply_destination_for_event(event)
|
||||
log.debug(u"replypath: %s", replypath)
|
||||
|
||||
if replystr is not None:
|
||||
recursing = getattr(event, '_recursing', False)
|
||||
log.debug("determined recursing to be %s", recursing)
|
||||
if recursing:
|
||||
return replystr
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user