async def me(text: str, conn: IrcClient, chan: str, nick: str,
             event: CommandEvent) -> None:
    """
    [#channel] <action> - acts out <action> in a [#channel], or in the current channel of none is specified
    """
    channel, text = get_chan(chan, text)
    event.admin_log('{} used ME to make me ACT "{}" in {}.'.format(
        nick, text, channel))
    conn.ctcp(channel, "ACTION", text)
def test_crypto_cmd(mock_requests):
    init_response(mock_requests)

    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text="BTC USD",
        cmd_prefix=".",
        triggered_command="crypto",
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel="#foo",
        nick="foobaruser",
    )
    res = wrap_hook_response(cryptocurrency.crypto_command, event)

    assert res == [
        HookResult(
            return_type="return",
            value="BTC (bitcoin) // \x0307$50,000,000,000.00\x0f USD - 2.0000000 BTC // \x0303+18.9%\x0f change",
        )
    ]
Exemple #3
0
def wrap_event(_hook, event, cmd, args):
    cmd_event = CommandEvent(base_event=event,
                             text=args.strip(),
                             triggered_command=cmd,
                             hook=_hook,
                             cmd_prefix='')
    return cmd_event
Exemple #4
0
def test_crypto_cmd(mock_requests):
    init_response(mock_requests)

    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text='BTC USD',
        cmd_prefix='.',
        triggered_command='crypto',
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel='#foo',
        nick='foobaruser',
    )
    res = wrap_hook_response(cryptocurrency.crypto_command, event)

    assert res == [
        HookResult(
            return_type='return',
            value=
            'BTC (bitcoin) // \x0307$50,000,000,000.00\x0f USD - 2.0000000 BTC // \x0303+18.9%\x0f change',
        )
    ]
Exemple #5
0
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)
Exemple #6
0
def _do_test(
    plugin_name,
    loader,
    data_name,
    cmd,
    text: Optional[str] = "test _ data",
    is_nick_valid=None,
    nick=None,
    bot_nick=None,
):
    plugin = importlib.import_module("plugins." + plugin_name)
    bot = MagicMock()
    bot.data_dir = "data"
    bot.loop = asyncio.get_event_loop()
    event = Event(
        hook=MagicMock(),
        bot=bot,
        conn=MagicMock(),
        channel="#foo",
        nick=nick or "foobar",
    )
    if bot_nick:
        event.conn.nick = bot_nick
    else:
        event.conn.nick = "TestBot"

    if is_nick_valid:
        event.is_nick_valid = is_nick_valid

    if loader:
        _call(getattr(plugin, loader), event)

    if data_name:
        assert getattr(plugin, data_name)

    cmd_func = getattr(plugin, cmd)
    cmd_event = CommandEvent(
        text=text or "",
        cmd_prefix=".",
        hook=MagicMock(),
        triggered_command="foo",
        base_event=event,
    )
    if is_nick_valid:
        cmd_event.is_nick_valid = is_nick_valid

    return _call(cmd_func, cmd_event), cmd_event
Exemple #7
0
def test_parse_no_results(mock_requests, patch_try_shorten, mock_db):
    mock_requests.add('GET',
                      'https://maps.googleapis.com/maps/api/geocode/json',
                      json={
                          'status': 'OK',
                          'results': [],
                      })

    from plugins import weather

    weather.table.create(mock_db.engine, True)

    bot = MockBot(
        {
            'api_keys': {
                'google_dev_key': 'AIzatestapikey',
                'darksky': 'abc12345' * 4,
            }
        }, mock_db)

    weather.create_maps_api(bot)

    conn = MagicMock()
    conn.config = {}

    conn.bot = bot

    cmd_event = CommandEvent(text='myloc',
                             cmd_prefix='.',
                             triggered_command='we',
                             hook=MagicMock(),
                             bot=bot,
                             conn=conn,
                             channel='#foo',
                             nick='foobaruser')

    cmd_event.hook.required_args = ['event', 'db']
    cmd_event.hook.doc = "- foobar"

    cmd_event.prepare_threaded()

    res = wrap_hook_response(weather.check_and_parse, cmd_event)
    assert res == [('return', (None, "Unable to find location 'myloc'"))]
Exemple #8
0
 def call(self, text: str, results=None):
     event = CommandEvent(
         cmd_prefix=".",
         hook=MagicMock(),
         text=text,
         triggered_command="tv",
         conn=MagicMock(),
         channel="#foo",
         nick="nick",
     )
     return wrap_hook_response(self.get_func(), event, results=results)
Exemple #9
0
def _do_test(plugin_name,
             loader,
             data_name,
             cmd,
             text='test _ data',
             is_nick_valid=None,
             nick=None,
             bot_nick=None):
    plugin = importlib.import_module('plugins.' + plugin_name)
    bot = MagicMock()
    bot.data_dir = 'data'
    bot.loop = asyncio.get_event_loop()
    event = Event(hook=MagicMock(),
                  bot=bot,
                  conn=MagicMock(),
                  channel='#foo',
                  nick=nick or 'foobar')
    if bot_nick:
        event.conn.nick = bot_nick
    else:
        event.conn.nick = 'TestBot'

    if is_nick_valid:
        event.is_nick_valid = is_nick_valid

    if loader:
        _call(getattr(plugin, loader), event)

    if data_name:
        assert getattr(plugin, data_name)

    cmd_func = getattr(plugin, cmd)
    cmd_event = CommandEvent(text=text or '',
                             cmd_prefix='.',
                             hook=MagicMock(),
                             triggered_command='foo',
                             base_event=event)
    if is_nick_valid:
        cmd_event.is_nick_valid = is_nick_valid

    return _call(cmd_func, cmd_event), cmd_event
def do_search(query, results=None):
    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    cmd_event = CommandEvent(text=query,
                             cmd_prefix='.',
                             triggered_command='wiki',
                             hook=MagicMock(),
                             bot=conn.bot,
                             conn=conn,
                             channel='#foo',
                             nick='foobaruser')

    return wrap_hook_response(wikipedia.wiki, cmd_event, results=results)
def _run_alias():
    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text="",
        cmd_prefix=".",
        triggered_command="btc",
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel="#foo",
        nick="foobaruser",
    )
    return wrap_hook_response(cryptocurrency.btc_alias, event)
Exemple #12
0
def _run_alias():
    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text='',
        cmd_prefix='.',
        triggered_command='btc',
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel='#foo',
        nick='foobaruser',
    )
    return wrap_hook_response(cryptocurrency.btc_alias, event)
Exemple #13
0
def test_rounding(mock_requests, patch_try_shorten, mock_db):
    from plugins import weather
    bot = setup_api(mock_requests, mock_db)

    conn = MagicMock()
    conn.config = {}

    conn.bot = bot

    cmd_event = CommandEvent(text='',
                             cmd_prefix='.',
                             triggered_command='we',
                             hook=MagicMock(),
                             bot=bot,
                             conn=conn,
                             channel='#foo',
                             nick='foobar')

    weather.location_cache.append(('foobar', 'test location'))

    new_data = deepcopy(FIO_DATA)

    new_data['json']['currently']['temperature'] = 31.9

    mock_requests.add(mock_requests.GET,
                      re.compile(r'^https://api\.darksky\.net/forecast/.*'),
                      **new_data)

    out_text = (
        '(foobar) \x02Current\x02: foobar, 32F/0C\x0f; \x02High\x02: 64F/18C\x0f; '
        '\x02Low\x02: 57F/14C\x0f; \x02Humidity\x02: 45%\x0f; '
        '\x02Wind\x02: 12MPH/20KPH SE\x0f '
        '-- 123 Test St, Example City, CA - '
        '\x1fhttps://darksky.net/forecast/30.123,123.456\x0f '
        '(\x1dTo get a forecast, use .fc\x1d)')

    calls = [(
        'message',
        (
            '#foo',
            out_text,
        ),
        {},
    )]

    assert wrap_hook_response(weather.weather, cmd_event) == calls
Exemple #14
0
async def test_launch(
        mock_manager, patch_import_module, do_sieve,
        sieve_allow, single_thread
):
    called = False
    sieve_called = False

    @hook.command('test', do_sieve=do_sieve, singlethread=single_thread)
    def foo_cb():
        nonlocal called
        called = True

    @hook.sieve()
    def sieve_cb(_bot, _event, _hook):
        nonlocal sieve_called
        sieve_called = True
        if sieve_allow:
            return _event

        return None

    mod = MockModule()

    mod.sieve_cb = sieve_cb
    mod.foo_cb = foo_cb

    patch_import_module.return_value = mod

    await mock_manager.load_plugin('plugins/test.py')

    from cloudbot.event import CommandEvent

    event = CommandEvent(
        bot=mock_manager.bot,
        hook=mock_manager.commands['test'],
        cmd_prefix='.',
        text='',
        triggered_command='test',
    )

    result = await mock_manager.launch(event.hook, event)

    assert result == called and called == (sieve_allow or not do_sieve)
    assert sieve_called == do_sieve
Exemple #15
0
def test_crypto_cmd_bad_fiat(mock_requests):
    init_response(mock_requests, quote=False)

    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text='BTC ABC',
        cmd_prefix='.',
        triggered_command='crypto',
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel='#foo',
        nick='foobaruser',
    )
    res = wrap_hook_response(cryptocurrency.crypto_command, event)

    assert res == [HookResult('return', "Unknown fiat currency 'ABC'")]
Exemple #16
0
async def test_join(input_text, chan, key):
    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text=input_text,
        cmd_prefix=".",
        triggered_command="join",
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel="#foo",
        nick="foobaruser",
    )

    await async_util.run_func_with_args(asyncio.get_event_loop(),
                                        admin_bot.join, event)

    event.conn.join.assert_called_with(chan, key)
def test_crypto_cmd_bad_fiat(mock_requests):
    init_response(mock_requests, quote=False)

    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text="BTC ABC",
        cmd_prefix=".",
        triggered_command="crypto",
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel="#foo",
        nick="foobaruser",
    )
    res = wrap_hook_response(cryptocurrency.crypto_command, event)

    assert res == [HookResult("return", "Unknown fiat currency 'ABC'")]
def test_cmd_api_error(mock_requests):
    init_response(mock_requests, error_msg="FooBar")
    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text="BTC USD",
        cmd_prefix=".",
        triggered_command="crypto",
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel="#foo",
        nick="foobaruser",
    )
    res = []
    with pytest.raises(cryptocurrency.APIError, match="FooBar"):
        wrap_hook_response(cryptocurrency.crypto_command, event, res)

    assert res == [HookResult("message", ("#foo", "(foobaruser) Unknown API error"))]
def make_command_event(chan: Optional[str] = "#foo") -> CommandEvent:
    conn = MagicMock()
    conn.name = "foobarconn"
    conn.config = {}
    conn.bot = MagicMock()

    hook = MagicMock()
    hook.type = "command"
    hook.function_name = "foo"
    event = CommandEvent(
        text="bar",
        cmd_prefix=".",
        triggered_command="foo",
        hook=hook,
        bot=conn.bot,
        conn=conn,
        channel=chan,
        nick="foobaruser",
        user="******",
        host="host",
    )
    return event
Exemple #20
0
def test_cmd_api_error(mock_requests):
    init_response(mock_requests, error_msg='FooBar')
    conn = MagicMock()
    conn.config = {}
    conn.bot = None

    event = CommandEvent(
        text='BTC USD',
        cmd_prefix='.',
        triggered_command='crypto',
        hook=MagicMock(),
        bot=conn.bot,
        conn=conn,
        channel='#foo',
        nick='foobaruser',
    )
    res = []
    with pytest.raises(cryptocurrency.APIError, match='FooBar'):
        wrap_hook_response(cryptocurrency.crypto_command, event, res)

    assert res == [
        HookResult('message', ('#foo', '(foobaruser) Unknown API error'))
    ]
def test_rate_limit_command() -> None:
    conn = MagicMock()
    conn.name = "foobarconn"
    conn.config = {}
    conn.bot = MagicMock()

    hook = MagicMock()
    hook.type = "command"
    event = CommandEvent(
        text="bar",
        cmd_prefix=".",
        triggered_command="foo",
        hook=hook,
        bot=conn.bot,
        conn=conn,
        channel="#foo",
        nick="foobaruser",
    )
    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
Exemple #22
0
def test_find_location(mock_requests, patch_try_shorten, mock_db):
    from plugins import weather
    bot = MockBot({}, mock_db)
    weather.create_maps_api(bot)
    weather.location_cache.clear()
    assert weather.data.maps_api is None

    bot = setup_api(mock_requests, mock_db)

    assert weather.find_location('Foo Bar') == {
        'lat': 30.123,
        'lng': 123.456,
        'address': '123 Test St, Example City, CA',
    }

    conn = MagicMock()
    conn.config = {}

    conn.bot = bot

    cmd_event = CommandEvent(text='',
                             cmd_prefix='.',
                             triggered_command='we',
                             hook=MagicMock(),
                             bot=bot,
                             conn=conn,
                             channel='#foo',
                             nick='foobar')

    cmd_event.hook.required_args = ['db']
    cmd_event.hook.doc = "- foobar"

    cmd_event.prepare_threaded()

    assert wrap_hook_response(weather.weather, cmd_event) == [
        ('notice', ('foobar', '.we - foobar'), {})
    ]
    weather.location_cache.append(('foobar', 'test location'))

    mock_requests.add(mock_requests.GET,
                      re.compile(r'^https://api\.darksky\.net/forecast/.*'),
                      **FIO_DATA)
    assert wrap_hook_response(weather.weather, cmd_event) == [(
        'message',
        (
            '#foo',
            '(foobar) \x02Current\x02: foobar, 68F/20C\x0f; \x02High\x02: 64F/18C\x0f; '
            '\x02Low\x02: 57F/14C\x0f; \x02Humidity\x02: 45%\x0f; '
            '\x02Wind\x02: 12MPH/20KPH SE\x0f '
            '-- 123 Test St, Example City, CA - '
            '\x1fhttps://darksky.net/forecast/30.123,123.456\x0f '
            '(\x1dTo get a forecast, use .fc\x1d)',
        ),
        {},
    )]
    assert wrap_hook_response(weather.forecast, cmd_event) == [(
        'message',
        (
            '#foo',
            '(foobar) \x02Today\x02: foobar; High: 64F/18C; Low: 57F/14C; '
            'Humidity: 45%; Wind: 15MPH/24KPH SE | '
            '\x02Tomorrow\x02: foobar; High: 64F/18C; '
            'Low: 57F/14C; Humidity: 45%; Wind: 15MPH/24KPH SE '
            '-- 123 Test St, Example City, CA - '
            '\x1fhttps://darksky.net/forecast/30.123,123.456\x0f',
        ),
        {},
    )]

    mock_requests.reset()
    mock_requests.add(mock_requests.GET,
                      'https://maps.googleapis.com/maps/api/geocode/json',
                      json={'status': 'foobar'})

    response = []
    with pytest.raises(ApiError):
        wrap_hook_response(weather.weather, cmd_event, response)

    assert response == [('message', ('#foo', '(foobar) API Error occurred.'),
                         {})]

    bot.config['api_keys']['google_dev_key'] = None
    bot.config.load_config()
    weather.create_maps_api(bot)
    assert wrap_hook_response(weather.weather, cmd_event) == [
        ('return',
         'This command requires a Google Developers Console API key.')
    ]
    assert wrap_hook_response(weather.forecast, cmd_event) == [
        ('return',
         'This command requires a Google Developers Console API key.')
    ]

    bot.config['api_keys']['darksky'] = None
    bot.config.load_config()
    weather.create_maps_api(bot)
    assert wrap_hook_response(weather.weather, cmd_event) == [
        ('return', 'This command requires a DarkSky API key.')
    ]
    assert wrap_hook_response(weather.forecast, cmd_event) == [
        ('return', 'This command requires a DarkSky API key.')
    ]

    # Test DB storage
    bot.config.update({
        'api_keys': {
            'google_dev_key': 'AIzatestapikey',
            'darksky': 'abc12345' * 4,
        }
    })
    bot.config.load_config()
    weather.create_maps_api(bot)
    weather.table.create(mock_db.engine, checkfirst=True)
    cmd_event.db = mock_db.session()
    cmd_event.text = 'my location'

    weather.load_cache(mock_db.session())
    mock_requests.reset()
    setup_api(mock_requests, mock_db)
    mock_requests.add(mock_requests.GET,
                      re.compile(r'^https://api\.darksky\.net/forecast/.*'),
                      **FIO_DATA)

    (loc, data), err = call_with_args(weather.check_and_parse, cmd_event)
    assert loc == {
        'address': '123 Test St, Example City, CA',
        'lat': 30.123,
        'lng': 123.456
    }
    assert data is not None
    assert err is None

    assert weather.location_cache == [(cmd_event.nick, cmd_event.text)]

    db_data = mock_db.session().execute(weather.table.select()).fetchall()
    assert len(db_data) == 1
    assert list(db_data[0]) == [cmd_event.nick, cmd_event.text]
Exemple #23
0
    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)
Exemple #24
0
    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)