def test_hook_args(hook): bot = MockBot() if hook.type in ( "irc_raw", "perm_check", "periodic", "on_start", "on_stop", "event", "on_connect", ): event = Event(bot=bot) elif hook.type == "command": event = CommandEvent(bot=bot, hook=hook, text="", triggered_command="", cmd_prefix=".") elif hook.type == "regex": event = RegexEvent(bot=bot, hook=hook, match=None) elif hook.type.startswith("on_cap"): event = CapEvent(bot=bot, cap="") elif hook.type == "post_hook": event = PostHookEvent(bot=bot) elif hook.type == "irc_out": event = IrcOutEvent(bot=bot) elif hook.type == "sieve": return else: # pragma: no cover assert False, "Unhandled hook type '{}' in tests".format(hook.type) for arg in hook.required_args: assert hasattr( event, arg), "Undefined parameter '{}' for hook function".format(arg)
def test_rate_limit_regex() -> None: conn = MagicMock() conn.name = "foobarconn" conn.config = {} conn.bot = MagicMock() hook = MagicMock() hook.type = "regex" event = RegexEvent( hook=hook, bot=conn.bot, conn=conn, channel="#foo", nick="foobaruser", match=MagicMock(), ) for _ in range(3): res = core_sieve.rate_limit(event.bot, event, event.hook) assert res is event res = core_sieve.rate_limit(event.bot, event, event.hook) assert res is None
async def process(self, event): """ :type event: Event """ run_before_tasks = [] tasks = [] halted = False def add_hook(hook, _event, _run_before=False): nonlocal halted if halted: return False if hook.clients and _event.conn.type not in hook.clients: return True coro = self.plugin_manager.launch(hook, _event) if _run_before: run_before_tasks.append(coro) else: tasks.append(coro) if hook.action is Action.HALTALL: halted = True return False if hook.action is Action.HALTTYPE: return False return True # Raw IRC hook for raw_hook in self.plugin_manager.catch_all_triggers: # run catch-all coroutine hooks before all others - TODO: Make this a plugin argument run_before = not raw_hook.threaded if not add_hook(raw_hook, Event(hook=raw_hook, base_event=event), _run_before=run_before): # The hook has an action of Action.HALT* so stop adding new tasks break if event.irc_command in self.plugin_manager.raw_triggers: for raw_hook in self.plugin_manager.raw_triggers[ event.irc_command]: if not add_hook(raw_hook, Event(hook=raw_hook, base_event=event)): # The hook has an action of Action.HALT* so stop adding new tasks break # Event hooks if event.type in self.plugin_manager.event_type_hooks: for event_hook in self.plugin_manager.event_type_hooks[event.type]: if not add_hook(event_hook, Event(hook=event_hook, base_event=event)): # The hook has an action of Action.HALT* so stop adding new tasks break matched_command = False if event.type is EventType.message: # Commands cmd_match = get_cmd_regex(event).match(event.content) if cmd_match: command_prefix = event.conn.config.get('command_prefix', '.') prefix = cmd_match.group('prefix') or command_prefix[0] command = cmd_match.group('command').lower() text = cmd_match.group('text').strip() cmd_event = partial(CommandEvent, text=text, triggered_command=command, base_event=event, cmd_prefix=prefix) if command in self.plugin_manager.commands: command_hook = self.plugin_manager.commands[command] command_event = cmd_event(hook=command_hook) add_hook(command_hook, command_event) matched_command = True else: potential_matches = [] for potential_match, plugin in self.plugin_manager.commands.items( ): if potential_match.startswith(command): potential_matches.append((potential_match, plugin)) if potential_matches: matched_command = True if len(potential_matches) == 1: command_hook = potential_matches[0][1] command_event = cmd_event(hook=command_hook) add_hook(command_hook, command_event) else: commands = sorted( command for command, plugin in potential_matches) txt_list = formatting.get_text_list(commands) event.notice( "Possible matches: {}".format(txt_list)) if event.type in (EventType.message, EventType.action): # Regex hooks regex_matched = False for regex, regex_hook in self.plugin_manager.regex_hooks: if not regex_hook.run_on_cmd and matched_command: continue if regex_hook.only_no_match and regex_matched: continue regex_match = regex.search(event.content) if regex_match: regex_matched = True regex_event = RegexEvent(hook=regex_hook, match=regex_match, base_event=event) if not add_hook(regex_hook, regex_event): # The hook has an action of Action.HALT* so stop adding new tasks break # Run the tasks await asyncio.gather(*run_before_tasks, loop=self.loop) await asyncio.gather(*tasks, loop=self.loop)
def process(self, event): """ :type event: Event """ run_before_tasks = [] tasks = [] command_prefix = event.conn.config.get('command_prefix', '.') # Raw IRC hook for raw_hook in self.plugin_manager.catch_all_triggers: # run catch-all coroutine hooks before all others - TODO: Make this a plugin argument if not raw_hook.threaded: run_before_tasks.append( self.plugin_manager.launch( raw_hook, Event(hook=raw_hook, base_event=event))) else: tasks.append( self.plugin_manager.launch( raw_hook, Event(hook=raw_hook, base_event=event))) if event.irc_command in self.plugin_manager.raw_triggers: for raw_hook in self.plugin_manager.raw_triggers[ event.irc_command]: tasks.append( self.plugin_manager.launch( raw_hook, Event(hook=raw_hook, base_event=event))) # Event hooks if event.type in self.plugin_manager.event_type_hooks: for event_hook in self.plugin_manager.event_type_hooks[event.type]: tasks.append( self.plugin_manager.launch( event_hook, Event(hook=event_hook, base_event=event))) if event.type is EventType.message: # Commands if event.chan.lower() == event.nick.lower( ): # private message, no command prefix command_re = r'(?i)^(?:[{}]?|{}[,;:]+\s+)(\w+)(?:$|\s+)(.*)'.format( command_prefix, event.conn.nick) else: command_re = r'(?i)^(?:[{}]|{}[,;:]+\s+)(\w+)(?:$|\s+)(.*)'.format( command_prefix, event.conn.nick) cmd_match = re.match(command_re, event.content) if cmd_match: command = cmd_match.group(1).lower() if command in self.plugin_manager.commands: command_hook = self.plugin_manager.commands[command] command_event = CommandEvent( hook=command_hook, text=cmd_match.group(2).strip(), triggered_command=command, base_event=event) tasks.append( self.plugin_manager.launch(command_hook, command_event)) else: potential_matches = [] for potential_match, plugin in self.plugin_manager.commands.items( ): if potential_match.startswith(command): potential_matches.append((potential_match, plugin)) if potential_matches: if len(potential_matches) == 1: command_hook = potential_matches[0][1] command_event = CommandEvent( hook=command_hook, text=cmd_match.group(2).strip(), triggered_command=command, base_event=event) tasks.append( self.plugin_manager.launch( command_hook, command_event)) else: event.notice("Possible matches: {}".format( formatting.get_text_list([ command for command, plugin in potential_matches ]))) # Regex hooks for regex, regex_hook in self.plugin_manager.regex_hooks: if not regex_hook.run_on_cmd and cmd_match: pass else: regex_match = regex.search(event.content) if regex_match: regex_event = RegexEvent(hook=regex_hook, match=regex_match, base_event=event) tasks.append( self.plugin_manager.launch(regex_hook, regex_event)) # Run the tasks yield from asyncio.gather(*run_before_tasks, loop=self.loop) yield from asyncio.gather(*tasks, loop=self.loop)
def process(self, event): """ :type event: Event """ run_before_tasks = [] tasks = [] command_prefix = event.conn.config.get('command_prefix', '.') halted = False def add_hook(hook, _event, _run_before=False): nonlocal halted if halted: return False coro = self.plugin_manager.launch(hook, _event) if _run_before: run_before_tasks.append(coro) else: tasks.append(coro) if hook.action is Action.HALTALL: halted = True return False elif hook.action is Action.HALTTYPE: return False return True # Raw IRC hook for raw_hook in self.plugin_manager.catch_all_triggers: # run catch-all coroutine hooks before all others - TODO: Make this a plugin argument run_before = not raw_hook.threaded if not add_hook(raw_hook, Event(hook=raw_hook, base_event=event), _run_before=run_before): # The hook has an action of Action.HALT* so stop adding new tasks break if event.irc_command in self.plugin_manager.raw_triggers: for raw_hook in self.plugin_manager.raw_triggers[ event.irc_command]: if not add_hook(raw_hook, Event(hook=raw_hook, base_event=event)): # The hook has an action of Action.HALT* so stop adding new tasks break # Event hooks if event.type in self.plugin_manager.event_type_hooks: for event_hook in self.plugin_manager.event_type_hooks[event.type]: if not add_hook(event_hook, Event(hook=event_hook, base_event=event)): # The hook has an action of Action.HALT* so stop adding new tasks break if event.type is EventType.message: # Commands if event.chan.lower() == event.nick.lower( ): # private message, no command prefix command_re = r'(?i)^(?:[{}]?|{}[,;:]+\s+)(\w+)(?:$|\s+)(.*)' else: command_re = r'(?i)^(?:[{}]|{}[,;:]+\s+)(\w+)(?:$|\s+)(.*)' cmd_match = re.match( command_re.format(command_prefix, event.conn.nick), event.content_raw) if cmd_match: command = cmd_match.group(1).lower() text = irc_clean(cmd_match.group(2).strip()) if command in self.plugin_manager.commands: command_hook = self.plugin_manager.commands[command] command_event = CommandEvent(hook=command_hook, text=text, triggered_command=command, base_event=event) add_hook(command_hook, command_event) else: potential_matches = [] for potential_match, plugin in self.plugin_manager.commands.items( ): if potential_match.startswith(command): potential_matches.append((potential_match, plugin)) if potential_matches: if len(potential_matches) == 1: command_hook = potential_matches[0][1] command_event = CommandEvent( hook=command_hook, text=text, triggered_command=command, base_event=event) add_hook(command_hook, command_event) else: event.notice("Possible matches: {}".format( formatting.get_text_list([ command for command, plugin in potential_matches ]))) # Regex hooks regex_matched = False for regex, regex_hook in self.plugin_manager.regex_hooks: if not regex_hook.run_on_cmd and cmd_match: continue if regex_hook.only_no_match and regex_matched: continue regex_match = regex.search(event.content) if regex_match: regex_matched = True regex_event = RegexEvent(hook=regex_hook, match=regex_match, base_event=event) if not add_hook(regex_hook, regex_event): # The hook has an action of Action.HALT* so stop adding new tasks break # Run the tasks yield from asyncio.gather(*run_before_tasks, loop=self.loop) yield from asyncio.gather(*tasks, loop=self.loop)
def process(self, event): """ :type event: Event """ run_before_tasks = [] tasks = [] halted = False def add_hook(hook, _event, _run_before=False): nonlocal halted if halted: return False if hook.clients and _event.conn.type not in hook.clients: return True coro = self.plugin_manager.launch(hook, _event) if _run_before: run_before_tasks.append(coro) else: tasks.append(coro) if hook.action is Action.HALTALL: halted = True return False elif hook.action is Action.HALTTYPE: return False return True # Raw IRC hook for raw_hook in self.plugin_manager.catch_all_triggers: # run catch-all coroutine hooks before all others - TODO: Make this a plugin argument run_before = not raw_hook.threaded if not add_hook(raw_hook, Event(hook=raw_hook, base_event=event), _run_before=run_before): # The hook has an action of Action.HALT* so stop adding new tasks break if event.irc_command in self.plugin_manager.raw_triggers: for raw_hook in self.plugin_manager.raw_triggers[event.irc_command]: if not add_hook(raw_hook, Event(hook=raw_hook, base_event=event)): # The hook has an action of Action.HALT* so stop adding new tasks break # Event hooks if event.type in self.plugin_manager.event_type_hooks: for event_hook in self.plugin_manager.event_type_hooks[event.type]: if not add_hook(event_hook, Event(hook=event_hook, base_event=event)): # The hook has an action of Action.HALT* so stop adding new tasks break matched_command = False if event.type is EventType.message: # Commands cmd_match = get_cmd_regex_match(event) if cmd_match: command_prefix = event.conn.config.get('command_prefix', '.') prefix = cmd_match.group('prefix') or command_prefix command = cmd_match.group('command').lower() text = cmd_match.group('text').strip() cmd_event = partial( CommandEvent, text=text, triggered_command=command, base_event=event, cmd_prefix=prefix ) if command in self.plugin_manager.commands: command_hook = self.plugin_manager.commands[command] command_event = cmd_event(hook=command_hook) add_hook(command_hook, command_event) matched_command = True else: potential_matches = {} for alias, hook in self.plugin_manager.commands.items(): if alias.startswith(command): # only list commands the user has permissions for if not event.check_permissions(hook.permissions, notice=False): continue # plugin + function name groups aliases key = hook.plugin.title + hook.function_name if key not in potential_matches: # First item is always the hook potential_matches[key] = [hook] potential_matches[key].append(alias) ## if potential_matches: matched_command = True if len(potential_matches) == 1: command_hook = next(iter(potential_matches.values()))[0] command_event = cmd_event(hook=command_hook) add_hook(command_hook, command_event) else: sorted_cmds = sorted( ["/".join((aliases[1:])) for aliases in potential_matches.values()]) event.reply("Possible matches: " + ", ".join(sorted_cmds)) if event.type in (EventType.message, EventType.action): # Regex hooks regex_matched = False for regex, regex_hook in self.plugin_manager.regex_hooks: if not regex_hook.run_on_cmd and matched_command: continue if regex_hook.only_no_match and regex_matched: continue regex_match = regex.search(event.content) if regex_match: regex_matched = True regex_event = RegexEvent(hook=regex_hook, match=regex_match, base_event=event) if not add_hook(regex_hook, regex_event): # The hook has an action of Action.HALT* so stop adding new tasks break # Run the tasks yield from asyncio.gather(*run_before_tasks, loop=self.loop) yield from asyncio.gather(*tasks, loop=self.loop)