Beispiel #1
0
    def test_handle_webhook(self):
        # Create an initialized plugin so its listeners are registered
        driver = Driver()
        plugin = WebHookExample().initialize(driver, Settings())
        # Construct a handler with it
        handler = EventHandler(driver, Settings(), plugins=[plugin])

        # Mock the call_function of the plugin so we can make some asserts
        async def mock_call_function(function, event, groups):
            # This is the regexp that we're trying to trigger
            assert function.matcher.pattern == "ping"
            assert event.text == "hello!"
            assert groups == []

        with mock.patch.object(
            plugin, "call_function", wraps=mock_call_function
        ) as mocked:
            asyncio.run(
                handler._handle_webhook(
                    WebHookEvent(
                        body={"text": "hello!"},
                        request_id="request_id",
                        webhook_id="ping",
                    ),
                )
            )
            # Assert the function was called, so we know the asserts succeeded.
            mocked.assert_called_once()
Beispiel #2
0
def test_environment():
    assert Settings(MATTERMOST_URL="website.com").MATTERMOST_URL == "website.com"

    os.environ["MATTERMOST_URL"] = "test_site.org"
    os.environ["IGNORE_USERS"] = "me,someone_else"
    s = Settings(MATTERMOST_URL="website.com")
    assert s.MATTERMOST_URL == "test_site.org"
    # The environment variable should be parsed into a list.
    assert s.IGNORE_USERS == ["me", "someone_else"]
Beispiel #3
0
def test_constructor():
    default = Settings()
    assert default.MATTERMOST_URL == "chat.com"
    assert default.SCHEME == "https"
    assert default.IGNORE_USERS == []

    manual = Settings(
        MATTERMOST_URL="http://website.com", IGNORE_USERS=["me", "someone_else"]
    )
    assert manual.MATTERMOST_URL == "website.com"
    assert manual.SCHEME == "http"
    assert manual.IGNORE_USERS == ["me", "someone_else"]

    # Test default scheme
    assert Settings(MATTERMOST_URL="website.com").SCHEME == "https"
Beispiel #4
0
    def test_handle_post(self):
        # Create an initialized plugin so its listeners are registered
        driver = Driver()
        plugin = ExamplePlugin().initialize(driver)
        # Construct a handler with it
        handler = EventHandler(driver, Settings(), plugins=[plugin])

        # Mock the call_function of the plugin so we can make some asserts
        async def mock_call_function(function, message, groups):
            # This is the regexp that we're trying to trigger
            assert function.matcher.pattern == "sleep ([0-9]+)"
            assert message.text == "sleep 5"  # username should be stripped off
            assert groups == ["5"]  # arguments should be matched and passed explicitly

        with mock.patch.object(
            plugin, "call_function", wraps=mock_call_function
        ) as mocked:
            # Transform the default message into a raw post event so we can pass it
            new_body = create_message(text="@my_username sleep 5").body.copy()
            new_body["data"]["post"] = json.dumps(new_body["data"]["post"])
            new_body["data"]["mentions"] = json.dumps(new_body["data"]["mentions"])
            asyncio.run(handler._handle_post(new_body))

            # Assert the function was called, so we know the asserts succeeded.
            mocked.assert_called_once()
Beispiel #5
0
    def test_handle_event(self, handle_post):
        handler = EventHandler(Driver(), Settings(), plugins=[])
        # This event should trigger _handle_post
        asyncio.run(handler._handle_event(json.dumps(create_message().body)))
        # This event should not
        asyncio.run(handler._handle_event(json.dumps({"event": "some_other_event"})))

        handle_post.assert_called_once_with(create_message().body)
Beispiel #6
0
    def test_should_ignore(self):
        handler = EventHandler(
            Driver(), Settings(IGNORE_USERS=["ignore_me"]), plugins=[]
        )
        # We shouldn't ignore a message from betty, since she is not listed
        assert not handler._should_ignore(create_message(sender_name="betty"))
        assert handler._should_ignore(create_message(sender_name="ignore_me"))

        # We ignore our own messages by default
        assert handler._should_ignore(create_message(sender_name="my_username"))

        # But shouldn't do so if this is explicitly requested
        handler = EventHandler(
            Driver(),
            Settings(IGNORE_USERS=["ignore_me"]),
            plugins=[],
            ignore_own_messages=False,
        )
        assert not handler._should_ignore(create_message(sender_name="my_username"))
Beispiel #7
0
def driver():
    return Bot(
        settings=Settings(
            MATTERMOST_URL="http://127.0.0.1",
            BOT_TOKEN="7arqwr6kzibc58zomct9ndfk1e",
            MATTERMOST_PORT=8065,
            SSL_VERIFY=False,
            WEBHOOK_HOST_ENABLED=True,
            WEBHOOK_HOST_URL="http://127.0.0.1",
            WEBHOOK_HOST_PORT=8579,
        ),
        plugins=
        [],  # We only use this to send messages, not to reply to anything.
    ).driver
Beispiel #8
0
    def test_start(self, threadpool):
        # Test server startup with a different port so it won't clash with the
        # integration tests
        server = WebHookServer(port=3281, url=Settings().WEBHOOK_HOST_URL)
        threadpool.start_webhook_server_thread(server)
        threadpool.start()
        time.sleep(0.5)
        assert server.running

        asyncio.set_event_loop(asyncio.new_event_loop())

        # Run the other tests sequentially
        self.test_obtain_response(server)
        self.test_process_webhook(server)

        # Test shutdown procedure
        threadpool.stop()
        assert not server.running
Beispiel #9
0
def start_bot(request):
    lock = FileLock("./bot.lock")

    try:
        # We want to run the tests in multiple parallel processes, but launch at most
        # a single bot.
        lock.acquire(timeout=0.01)
        bot = Bot(
            settings=Settings(
                MATTERMOST_URL="http://127.0.0.1",
                BOT_TOKEN="e691u15hajdebcnqpfdceqihcc",
                MATTERMOST_PORT=8065,
                SSL_VERIFY=False,
                WEBHOOK_HOST_ENABLED=True,
                WEBHOOK_HOST_URL="http://127.0.0.1",
                WEBHOOK_HOST_PORT=8579,
            ),
            plugins=[TestPlugin(),
                     ExamplePlugin(),
                     WebHookExample()],
        )

        def run_bot():
            bot.run()

        # Start the bot now
        bot_process = Process(target=run_bot)
        bot_process.start()

        def stop_bot():
            time.sleep(5)
            bot_process.terminate()
            lock.release()

        # Once all tests are finished, stop the bot
        request.addfinalizer(stop_bot)

    except TimeoutError:
        # If the lock times out, it means a bot is already running and we don't need
        # to do anything here.
        pass

    finally:
        time.sleep(5)  # Give the bot some time to start up
Beispiel #10
0
    def test_init(self, login):
        # Create some plugins and mock their initialize method so we can check calls
        plugins = [ExamplePlugin(), TestPlugin()]
        for plugin in plugins:
            plugin.initialize = mock.MagicMock()

        # Create a bot and verify that it gets initialized correctly
        bot = Bot(
            settings=Settings(MATTERMOST_URL="test_url.org", BOT_TOKEN="random_token"),
            plugins=plugins,
        )
        assert bot.driver.options["url"] == "test_url.org"
        assert bot.driver.options["token"] == "random_token"
        assert bot.plugins == plugins
        login.assert_called_once()

        # Verify that all of the passed plugins were initialized
        for plugin in plugins:
            assert plugin.initialize.called_once_with(bot.driver)
Beispiel #11
0
    def test_click_function(self):
        @click.command()
        @click.option("--arg1", type=str, default="nothing")
        @click.option("--arg2", type=str, default="nothing either")
        @click.option("-f", "--flag", is_flag=True)
        def wrapped(self, message, arg1, arg2, flag):
            return arg1, arg2, flag

        f = MessageFunction(wrapped, matcher=re.compile(""))
        # Verify that the arguments are passed and returned correctly
        assert f(create_message(),
                 "--arg1=yes --arg2=no") == ("yes", "no", False)
        assert f(create_message(), "-f --arg2=no") == ("nothing", "no", True)

        # If an incorrect argument is passed, the error and help string should be returned.
        def mocked_reply(message, response):
            assert "no such option: --nonexistent-arg" in response
            assert f.docstring in response

        f.plugin = ExamplePlugin().initialize(Driver(), Settings())
        with mock.patch.object(f.plugin.driver, "reply_to",
                               wraps=mocked_reply) as mock_function:
            f(create_message(), "-f --arg2=no --nonexistent-arg")
            mock_function.assert_called_once()
Beispiel #12
0
    def test_init(self):
        handler = EventHandler(
            Driver(), Settings(), plugins=[ExamplePlugin(), WebHookExample()]
        )
        # Test the name matcher regexp
        assert handler._name_matcher.match("@my_username are you there?")
        assert not handler._name_matcher.match("@other_username are you there?")

        # Test that all listeners from the individual plugins are now registered on
        # the handler
        for plugin in handler.plugins:
            for pattern, listener in plugin.message_listeners.items():
                assert listener in handler.message_listeners[pattern]
            for pattern, listener in plugin.webhook_listeners.items():
                assert listener in handler.webhook_listeners[pattern]

        # And vice versa, check that any listeners on the handler come from the
        # registered plugins
        for pattern, listeners in handler.message_listeners.items():
            for listener in listeners:
                assert any(
                    [
                        pattern in plugin.message_listeners
                        and listener in plugin.message_listeners[pattern]
                        for plugin in handler.plugins
                    ]
                )
        for pattern, listeners in handler.webhook_listeners.items():
            for listener in listeners:
                assert any(
                    [
                        pattern in plugin.webhook_listeners
                        and listener in plugin.webhook_listeners[pattern]
                        for plugin in handler.plugins
                    ]
                )
Beispiel #13
0
from mmpy_bot import Bot, ExamplePlugin, Settings, WebHookExample

bot = Bot(
    # Either specify your settings here or use environment variables to override them.
    # See docker-compose.yml for an example you can use for local development.
    settings=Settings(),
    plugins=[ExamplePlugin(), WebHookExample()],  # Add your own plugins here.
)
bot.run()
Beispiel #14
0
def bot():
    bot = Bot(plugins=[ExamplePlugin()], settings=Settings(DEBUG=True))
    yield bot
    bot.stop()  # if the bot was started, stop it