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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user