DrBotIRC: add regex-matching global handlers
add_global_regex_handler and remove_global_regex_handler are new methods that work the same as irclib's non-regex versions, but check patterns before adding/removing. this allows for a more direct link between event loop and module methods i'm hoping that one day it will allow for the removal of ancient shortcuts that just get in the way now, like do() and on_pub_or_privmsg() lightly tested, if anything is still brittle it's recursion, no doubt
This commit is contained in:
parent
53a3c40102
commit
52970894a9
129
DrBotIRC.py
129
DrBotIRC.py
|
@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
"""
|
||||
|
||||
import bisect
|
||||
import copy
|
||||
from ConfigParser import NoOptionError, NoSectionError
|
||||
import logging
|
||||
|
@ -213,6 +214,8 @@ class DrBotIRC(irclib.IRC):
|
|||
self.config = config
|
||||
self.xmlrpc = None
|
||||
|
||||
self.regex_handlers = dict()
|
||||
|
||||
# handle SIGINT
|
||||
signal.signal(signal.SIGINT, self.sigint_handler)
|
||||
|
||||
|
@ -257,8 +260,62 @@ class DrBotIRC(irclib.IRC):
|
|||
|
||||
return self.server
|
||||
|
||||
def add_global_regex_handler(self, event, regex, handler, priority=0):
|
||||
"""Adds a global handler function for a specific event type and regex.
|
||||
|
||||
The handler function is called whenever the specified event is
|
||||
triggered in any of the connections and the regex matches.
|
||||
See documentation for the Event class.
|
||||
|
||||
The handler functions are called in priority order (lowest
|
||||
number is highest priority). If a handler function returns
|
||||
"NO MORE", no more handlers will be called.
|
||||
|
||||
This is basically an extension of add_global_handler(), either may
|
||||
work, though it turns out most modules probably want this one.
|
||||
|
||||
The provided method should take as arguments:
|
||||
* nick the nick creating the event, or None
|
||||
* userhost the userhost creating the event, or None
|
||||
* event the raw IRC event, which may be None
|
||||
* from_admin whether or not the event came from an admin
|
||||
* groups list of match.groups(), from re.search()
|
||||
|
||||
Args:
|
||||
event event type (a string), as in numeric_events
|
||||
regex regex string to match before doing callback invocation
|
||||
handler callback function to invoke
|
||||
priority integer, the lower number, the higher priority
|
||||
|
||||
"""
|
||||
|
||||
if not event in self.regex_handlers:
|
||||
self.regex_handlers[event] = []
|
||||
bisect.insort(self.regex_handlers[event], ((priority, regex, handler)))
|
||||
|
||||
def remove_global_regex_handler(self, event, regex, handler):
|
||||
"""Removes a global regex handler function.
|
||||
|
||||
Args:
|
||||
event event type (a string), as in numeric_events
|
||||
regex regex string that was used in matching
|
||||
handler callback function to remove
|
||||
|
||||
Returns:
|
||||
1 on success, otherwise 0.
|
||||
|
||||
"""
|
||||
|
||||
if not event in self.regex_handlers:
|
||||
return 0
|
||||
|
||||
for h in self.regex_handlers[event]:
|
||||
if regex == h[1] and handler == h[2]:
|
||||
self.regex_handlers[event].remove(h)
|
||||
return 1
|
||||
|
||||
def _handle_event(self, connection, event):
|
||||
"""Override event handler to do recursion.
|
||||
"""Override event handler to do recursion and regex checking.
|
||||
|
||||
Args:
|
||||
connection source connection
|
||||
|
@ -287,6 +344,41 @@ class DrBotIRC(irclib.IRC):
|
|||
self.try_recursion(connection, event)
|
||||
self.try_alias(connection, event)
|
||||
|
||||
nick = None
|
||||
userhost = None
|
||||
admin = False
|
||||
|
||||
if event.source() is not None:
|
||||
nick = irclib.nm_to_n(event.source())
|
||||
try:
|
||||
userhost = irclib.nm_to_uh(event.source())
|
||||
except IndexError: pass
|
||||
|
||||
try:
|
||||
if userhost == self.config.get('dr.botzo', 'admin_userhost'):
|
||||
admin = True
|
||||
except NoOptionError: pass
|
||||
|
||||
# try regex handlers first, since they're more specific
|
||||
rh = self.regex_handlers
|
||||
trh = sorted(rh.get('all_events', []) + rh.get(event.eventtype(), []))
|
||||
for handler in trh:
|
||||
try:
|
||||
prio, regex, method = handler
|
||||
for line in event.arguments():
|
||||
match = re.search(regex, line)
|
||||
if match:
|
||||
log.debug("pattern matched, calling "
|
||||
"{0:s}".format(method))
|
||||
# pattern matched, call method with pattern groups
|
||||
ret = method(nick, userhost, event, admin,
|
||||
match.groups())
|
||||
if ret == 'NO MORE':
|
||||
return
|
||||
except Exception as e:
|
||||
log.error("exception floated up to DrBotIrc!")
|
||||
log.exception(e)
|
||||
|
||||
h = self.handlers
|
||||
th = sorted(h.get('all_events', []) + h.get(event.eventtype(), []))
|
||||
for handler in th:
|
||||
|
@ -335,6 +427,41 @@ class DrBotIRC(irclib.IRC):
|
|||
|
||||
replies = []
|
||||
|
||||
nick = None
|
||||
userhost = None
|
||||
admin = False
|
||||
|
||||
if event.source() is not None:
|
||||
nick = irclib.nm_to_n(event.source())
|
||||
try:
|
||||
userhost = irclib.nm_to_uh(event.source())
|
||||
except IndexError: pass
|
||||
|
||||
try:
|
||||
if userhost == self.config.get('dr.botzo', 'admin_userhost'):
|
||||
admin = True
|
||||
except NoOptionError: pass
|
||||
|
||||
# try regex handlers first, since they're more specific
|
||||
rh = self.regex_handlers
|
||||
trh = sorted(rh.get('all_events', []) + rh.get(event.eventtype(), []))
|
||||
for handler in trh:
|
||||
try:
|
||||
prio, regex, method = handler
|
||||
for line in event.arguments():
|
||||
match = re.search(regex, line)
|
||||
if match:
|
||||
log.debug("pattern matched, calling "
|
||||
"{0:s}".format(method))
|
||||
# pattern matched, call method with pattern groups
|
||||
ret = method(nick, userhost, event, admin,
|
||||
match.groups())
|
||||
if ret:
|
||||
replies.append(ret)
|
||||
except Exception as e:
|
||||
log.error("exception floated up to DrBotIrc!")
|
||||
log.exception(e)
|
||||
|
||||
h = self.handlers
|
||||
th = sorted(h.get('all_events', []) + h.get(event.eventtype(), []))
|
||||
for handler in th:
|
||||
|
|
Loading…
Reference in New Issue