def test_help_for_command(self): self.object._bot.dispatcher = MessageDispatcher() self.object._bot.webserver = Webserver(test_host, test_port) self.object._bot.dispatcher.register_plugin(self.object) assert self.object.help(self.test_event, ["help"]) == format_docstring( "Displays help for each command" )
def __init__(self, config, test_mode=False): self.always_send_dm = [] self.config = config self.dispatcher = MessageDispatcher() self.event_handlers = {} self.is_setup = False self.log = logging.getLogger(type(self).__name__) self.plugins = PluginManager(self, test_mode) self.runnable = True self.sc = None self.webserver = None self.test_mode = test_mode self.reconnect_needed = True self.bot_start_time = None if self.test_mode: self.metrics = { 'startup_time': 0 } from slackminion.plugins.core import version self.version = version try: from slackminion.plugins.core import commit self.commit = commit except ImportError: self.commit = "HEAD"
def setUp(self, *args): self.object = AuthManager(bot=mock.Mock()) self.object._bot.dispatcher = MessageDispatcher() self.object._bot.api_client.users_find.return_value = TestUser() self.test_event = SlackEvent(event_type='tests', **test_payload) self.test_user = SlackUser(user_info=test_user_response['user'], api_client=self.object._bot.api_client) self.test_event.user = self.test_user
def __init__(self, config, test_mode=False, dev_mode=False): self.config = config self.dispatcher = MessageDispatcher() self.log = logging.getLogger(type(self).__name__) self.plugins = PluginManager(self, test_mode) self.test_mode = test_mode self.dev_mode = dev_mode self.event_loop = asyncio.get_event_loop() if self.test_mode: self.metrics = {'startup_time': 0} self.version = my_version try: from slackminion.plugins.core import commit self.commit = commit except ImportError: self.commit = "HEAD"
class Bot(object): def __init__(self, config, test_mode=False): self.always_send_dm = [] self.config = config self.dispatcher = MessageDispatcher() self.event_handlers = {} self.is_setup = False self.log = logging.getLogger(type(self).__name__) self.plugins = PluginManager(self, test_mode) self.runnable = True self.sc = None self.webserver = None self.test_mode = test_mode self.reconnect_needed = True self.bot_start_time = None if self.test_mode: self.metrics = { 'startup_time': 0 } from slackminion.plugins.core import version self.version = version try: from slackminion.plugins.core import commit self.commit = commit except ImportError: self.commit = "HEAD" def start(self): """Initializes the bot, plugins, and everything.""" self.bot_start_time = datetime.now() self.webserver = Webserver(self.config['webserver']['host'], self.config['webserver']['port']) self.plugins.load() self.plugins.load_state() self._find_event_handlers() self.sc = ThreadedSlackClient(self.config['slack_token']) self.always_send_dm = ['_unauthorized_'] if 'always_send_dm' in self.config: self.always_send_dm.extend(map(lambda x: '!' + x, self.config['always_send_dm'])) # Rocket is very noisy at debug logging.getLogger('Rocket.Errors.ThreadPool').setLevel(logging.INFO) self.is_setup = True if self.test_mode: self.metrics['startup_time'] = (datetime.now() - self.bot_start_time).total_seconds() * 1000.0 def _find_event_handlers(self): for name in dir(self): method = getattr(self, name) if callable(method) and hasattr(method, 'is_eventhandler'): for event in method.events: self.event_handlers[event] = method def run(self, start=True): """ Connects to slack and enters the main loop. * start - If True, rtm.start API is used. Else rtm.connect API is used For more info, refer to https://python-slackclient.readthedocs.io/en/latest/real_time_messaging.html#rtm-start-vs-rtm-connect """ # Fail out if setup wasn't run if not self.is_setup: raise NotSetupError # Start the web server self.webserver.start() first_connect = True try: while self.runnable: if self.reconnect_needed: if not self.sc.rtm_connect(with_team_state=start): return False self.reconnect_needed = False if first_connect: first_connect = False self.plugins.connect() # Get all waiting events - this always returns a list try: events = self.sc.rtm_read() except AttributeError: self.log.exception('Something has failed in the slack rtm library. This is fatal.') self.runnable = False events = [] except: self.log.exception('Unhandled exception in rtm_read()') self.reconnect_needed = True events = [] for e in events: try: self._handle_event(e) except KeyboardInterrupt: # Gracefully shutdown self.runnable = False except: self.log.exception('Unhandled exception in event handler') sleep(0.1) except KeyboardInterrupt: # On ctrl-c, just exit pass except: self.log.exception('Unhandled exception') def stop(self): """Does cleanup of bot and plugins.""" if self.webserver is not None: self.webserver.stop() if not self.test_mode: self.plugins.save_state() def send_message(self, channel, text, thread=None, reply_broadcast=None): """ Sends a message to the specified channel * channel - The channel to send to. This can be a SlackChannel object, a channel id, or a channel name (without the #) * text - String to send * thread - reply to the thread. See https://api.slack.com/docs/message-threading#threads_party * reply_broadcast - Set to true to indicate your reply is germane to all members of a channel """ # This doesn't want the # in the channel name if isinstance(channel, SlackRoomIMBase): channel = channel.id self.log.debug("Trying to send to %s: %s", channel, text) self.sc.rtm_send_message(channel, text, thread=thread, reply_broadcast=reply_broadcast) def send_im(self, user, text): """ Sends a message to a user as an IM * user - The user to send to. This can be a SlackUser object, a user id, or the username (without the @) * text - String to send """ if isinstance(user, SlackUser): user = user.id channelid = self._find_im_channel(user) else: channelid = user.id self.send_message(channelid, text) def _find_im_channel(self, user): resp = self.sc.api_call('im.list') channels = filter(lambda x: x['user'] == user, resp['ims']) if len(channels) > 0: return channels[0]['id'] resp = self.sc.api_call('im.open', user=user) return resp['channel']['id'] def _load_user_rights(self, user): if user is not None: if 'bot_admins' in self.config: if user.username in self.config['bot_admins']: user.is_admin = True def _handle_event(self, event): if 'type' not in event: # This is likely a notification that the bot was mentioned self.log.debug("Received odd event: %s", event) return e = SlackEvent(sc=self.sc, **event) self.log.debug("Received event type: %s", e.type) if e.user is not None: if hasattr(self, 'user_manager'): if not isinstance(e.user, SlackUser): self.log.debug("User is not SlackUser: %s", e.user) else: user = self.user_manager.get(e.user.id) if user is None: user = self.user_manager.set(e.user) e.user = user if e.type in self.event_handlers: self.event_handlers[e.type](e) @eventhandler(events='message') def _event_message(self, msg): self.log.debug("Message.message: %s: %s: %s", msg.channel, msg.user, msg.__dict__) # The user manager should load rights when a user is added if not hasattr(self, 'user_manager'): self._load_user_rights(msg.user) try: cmd, output = self.dispatcher.push(msg) except: self.log.exception('Unhandled exception') return self.log.debug("Output from dispatcher: %s", output) if output: if cmd in self.always_send_dm: self.send_im(msg.user, output) else: self.send_message(msg.channel, output) @eventhandler(events='error') def _event_error(self, msg): self.log.error("Received an error response from Slack: %s", msg.__dict__) @eventhandler(events='team_migration_started') def _event_team_migration_started(self, msg): self.log.warn("Slack has initiated a team migration to a new server. Attempting to reconnect...") self.reconnect_needed = True
class TestDispatcher(unittest.TestCase): @mock.patch('slackminion.slack.SlackUser') def setUp(self, mock_user): mock_user.return_value = test_user self.dispatcher = MessageDispatcher() self.p = DummyPlugin(None) self.test_payload = deepcopy(test_payload) def tearDown(self): self.dispatcher = None self.test_payload = None def test_register_plugin(self): self.dispatcher.register_plugin(self.p) def test_register_duplicate_plugin(self): self.dispatcher.register_plugin(self.p) with self.assertRaises(DuplicateCommandError) as e: self.dispatcher.register_plugin(self.p) self.assertIn('abc', str(e)) def test_get_command(self): self.dispatcher.register_plugin(self.p) method = self.dispatcher._get_command('!abc', None).method assert method == self.p.abc assert method(None, None) == 'abcba' def test_get_invalid_command(self): self.dispatcher.register_plugin(self.p) with self.assertRaises(KeyError): self.dispatcher._get_command('!def', None) def test_parse_message(self): e = SlackEvent(event_type='message', **{'data': { 'text': 'Hello world' }}) assert self.dispatcher._parse_message(e) == ['Hello', 'world'] def test_parse_message_unicode(self): e = SlackEvent(event_type='message', **{'data': { 'text': 'Hello\xa0world' }}) assert self.dispatcher._parse_message(e) == ['Hello', 'world'] @async_test async def test_strip_formatting(self): test_string = "!stripformat <@U123456> check <#C123456|test-channel> has <https://www.pinterest.com|www.pinterest.com>" expected_response = "@U123456 check #test-channel has www.pinterest.com" e = SlackEvent(event_type="message", **{"data": {"text": test_string}}) e.user = mock.Mock() e.channel = test_conversation self.dispatcher.register_plugin(self.p) cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd_opts.get("strip_formatting") is True self.assertEqual(expected_response, output) def test_unignore_nonignored_channel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get('api_client')) self.assertFalse(self.dispatcher.unignore(c)) assert 'testchannel' not in self.dispatcher.ignored_channels def test_ignore_duplicate_channel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get('api_client')) assert self.dispatcher.ignore(c) is True assert c.name in self.dispatcher.ignored_channels assert self.dispatcher.ignore(c) is False assert len(self.dispatcher.ignored_channels) == 1 def test_ignore_slackchannel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get('api_client')) c.name = 'testchannel' assert self.dispatcher.ignore(c) is True assert 'testchannel' in self.dispatcher.ignored_channels assert self.dispatcher._is_channel_ignored(self.p.abc, c) is True def test_unignore_slackchannel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get('api_client')) self.assertTrue(self.dispatcher.ignore(c)) self.assertTrue(self.dispatcher.unignore(c)) self.assertNotIn(test_channel.get('name'), self.dispatcher.ignored_channels) self.assertFalse(self.dispatcher._is_channel_ignored(self.p.abc, c)) @async_test async def test_push(self): self.dispatcher.register_plugin(self.p) self.test_payload['data'].update({'text': '!abc'}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == '!abc' assert output == 'abcba' assert type(cmd_opts) == dict assert ('reply_in_thread' in list(cmd_opts.keys())) is True assert ('reply_broadcast' in list(cmd_opts.keys())) is True assert cmd_opts.get('reply_broadcast') is False assert cmd_opts.get('reply_in_thread') is False @async_test async def test_push_alias(self): self.dispatcher.register_plugin(self.p) self.test_payload['data'].update({'text': '!bca'}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == '!bca' assert output == 'abcba' assert type(cmd_opts) == dict assert ('reply_in_thread' in list(cmd_opts.keys())) is True assert ('reply_broadcast' in list(cmd_opts.keys())) is True assert cmd_opts.get('reply_broadcast') is False assert cmd_opts.get('reply_in_thread') is False @async_test async def test_push_to_thread(self): self.dispatcher.register_plugin(self.p) self.test_payload['data'].update({'text': '!efg'}) e = SlackEvent(event_type="message", **self.test_payload) e.channel = test_conversation e.user = mock.Mock() cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == '!efg' assert output == 'efgfe' assert type(cmd_opts) == dict assert ('reply_in_thread' in list(cmd_opts.keys())) is True assert ('reply_broadcast' in list(cmd_opts.keys())) is True assert cmd_opts.get('reply_broadcast') is False assert cmd_opts.get('reply_in_thread') is True @async_test async def test_push_to_thread_with_broadcast(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload['data'].update({'text': '!hij'}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == '!hij' assert output == 'hijih' assert type(cmd_opts) == dict assert ('reply_in_thread' in list(cmd_opts.keys())) is True assert ('reply_broadcast' in list(cmd_opts.keys())) is True assert cmd_opts.get('reply_broadcast') is True assert cmd_opts.get('reply_in_thread') is True @async_test async def test_push_not_command(self): payload = dict(self.test_payload) payload['data'].update({'text': 'Not a command'}) e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_message_replied_event(self): payload = dict(self.test_payload) payload['data'].update({'subtype': 'message_replied'}) e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_no_user(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload['data'].update({'subtype': 'message_replied'}) payload['data'].pop('user') e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_ignored_channel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get('api_client')) self.dispatcher.ignore(c) self.dispatcher.register_plugin(self.p) self.dispatcher._is_channel_ignored = mock.Mock(return_value=True) self.test_payload['data'].update({ 'text': '!abc', 'user': test_user_id, 'channel': test_channel_id }) e = SlackEvent(event_type='message', **self.test_payload) e.channel = test_conversation e.user = mock.Mock() assert await self.dispatcher.push(e) == ('_ignored_', '', None) @async_test async def test_async_cmd(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload['data'].update({'text': '!asyncabc'}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == '!asyncabc' assert output == 'asyncabc response' assert type(cmd_opts) == dict assert ('reply_in_thread' in list(cmd_opts.keys())) is True assert ('reply_broadcast' in list(cmd_opts.keys())) is True assert ('parse' in list(cmd_opts.keys())) is True assert cmd_opts.get('reply_broadcast') is True assert cmd_opts.get('reply_in_thread') is True assert cmd_opts.get('parse') is None @async_test async def test_async_cmd_parse(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload['data'].update({'text': '!asyncparse'}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == '!asyncparse' assert output == 'async parse command #parse' assert type(cmd_opts) == dict assert ('reply_in_thread' in list(cmd_opts.keys())) is True assert ('reply_broadcast' in list(cmd_opts.keys())) is True assert ('parse' in list(cmd_opts.keys())) is True assert cmd_opts.get('reply_broadcast') is False assert cmd_opts.get('reply_in_thread') is False assert cmd_opts.get('parse') is True
def setUp(self, mock_user): mock_user.return_value = test_user self.dispatcher = MessageDispatcher() self.p = DummyPlugin(None) self.test_payload = deepcopy(test_payload)
def setup(self): self.object = MessageDispatcher() self.p = DummyPlugin(None)
class TestDispatcher(object): def setup(self): self.object = MessageDispatcher() self.p = DummyPlugin(None) def teardown(self): self.object = None def test_register_plugin(self): self.object.register_plugin(self.p) def test_register_duplicate_plugin(self): self.object.register_plugin(self.p) with pytest.raises(DuplicateCommandError) as e: self.object.register_plugin(self.p) assert 'abc' in str(e) def test_get_command(self): self.object.register_plugin(self.p) method = self.object._get_command('!abc', None).method assert method == self.p.abc assert method(None, None) == 'xyzzy' def test_get_invalid_command(self): self.object.register_plugin(self.p) with pytest.raises(KeyError): self.object._get_command('!def', None) def test_parse_message(self): e = SlackEvent(text='Hello world') assert self.object._parse_message(e) == ['Hello', 'world'] def test_ignore_channel(self): assert self.object.ignore('testchannel') is True assert 'testchannel' in self.object.ignored_channels def test_unignore_channel(self): assert self.object.ignore('testchannel') is True assert self.object.unignore('testchannel') is True assert 'testchannel' not in self.object.ignored_channels def test_unignore_nonignored_channel(self): self.object.unignore('testchannel') is False assert 'testchannel' not in self.object.ignored_channels def test_ignore_duplicate_channel(self): assert self.object.ignore('testchannel') is True assert 'testchannel' in self.object.ignored_channels assert self.object.ignore('testchannel') is False assert len(self.object.ignored_channels) == 1 def test_ignore_slackchannel(self): c = SlackChannel('CTEST') c.name = 'testchannel' assert self.object.ignore(c) is True assert 'testchannel' in self.object.ignored_channels assert self.object._is_channel_ignored(self.p.abc, c) is True def test_unignore_slackchannel(self): c = SlackChannel('CTEST') c.name = 'testchannel' assert self.object.ignore(c) is True assert self.object.unignore(c) is True assert 'testchannel' not in self.object.ignored_channels assert self.object._is_channel_ignored(self.p.abc, c) is False def test_push(self): self.object.register_plugin(self.p) e = SlackEvent(DummySlackConnection(), **{'text': '!abc', 'user': test_user_id, 'channel': test_channel_id}) assert self.object.push(e) == ('!abc', 'xyzzy') def test_push_alias(self): self.object.register_plugin(self.p) e = SlackEvent(DummySlackConnection(), **{'text': '!xyz', 'user': test_user_id, 'channel': test_channel_id}) assert self.object.push(e) == ('!xyz', 'xyzzy') def test_push_not_command(self): e = SlackEvent(DummySlackConnection(), **{'text': 'Not a command'}) assert self.object.push(e) == (None, None) def test_push_message_replied_event(self): e = SlackEvent(DummySlackConnection(), **{'subtype': 'message_replied'}) assert self.object.push(e) == (None, None) def test_push_no_user(self): self.object.register_plugin(self.p) e = SlackEvent(DummySlackConnection(), **{'text': '!abc'}) assert self.object.push(e) == (None, None) def test_push_ignored_channel(self): c = SlackChannel('CTEST') c.name = 'testchannel' self.object.ignore(c) self.object.register_plugin(self.p) e = SlackEvent(DummySlackConnection(), **{'text': '!abc', 'user': test_user_id, 'channel': test_channel_id}) assert self.object.push(e) == ('_ignored_', '')
def test_get_short_help_for_command(self): for command, helpstr in test_help_short_data: self.object._bot.dispatcher = MessageDispatcher() self.object._bot.dispatcher.register_plugin(DummyPlugin(self.object._bot)) assert self.object._get_short_help_for_command(command) == helpstr
class TestDispatcher(unittest.TestCase): @mock.patch("slackminion.slack.SlackUser") def setUp(self, mock_user): mock_user.return_value = test_user self.dispatcher = MessageDispatcher() self.p = DummyPlugin(None) self.test_payload = deepcopy(test_payload) def tearDown(self): self.dispatcher = None self.test_payload = None def test_register_plugin(self): self.dispatcher.register_plugin(self.p) def test_register_duplicate_plugin(self): self.dispatcher.register_plugin(self.p) with self.assertRaises(DuplicateCommandError) as e: self.dispatcher.register_plugin(self.p) self.assertIn("abc", str(e)) def test_get_command(self): self.dispatcher.register_plugin(self.p) method = self.dispatcher._get_command("!abc", None).method assert method == self.p.abc assert method(None, None) == "abcba" def test_get_invalid_command(self): self.dispatcher.register_plugin(self.p) with self.assertRaises(KeyError): self.dispatcher._get_command("!def", None) def test_parse_message(self): e = SlackEvent(event_type="message", **{"data": { "text": "Hello world" }}) assert self.dispatcher._parse_message(e) == ["Hello", "world"] def test_parse_message_extra_space(self): # Strip out extra spaces e = SlackEvent(event_type="message", **{"data": { "text": "Hello world" }}) assert self.dispatcher._parse_message(e) == ["Hello", "world"] def test_parse_message_unicode(self): e = SlackEvent(event_type="message", **{"data": { "text": "Hello\xa0world" }}) assert self.dispatcher._parse_message(e) == ["Hello", "world"] @async_test async def test_strip_formatting(self): test_string = "!stripformat <@U123456> check <#C123456|test-channel> has <https://www.pinterest.com|www.pinterest.com>" expected_response = "@U123456 check #test-channel has www.pinterest.com" e = SlackEvent(event_type="message", **{"data": {"text": test_string}}) e.user = mock.Mock() e.channel = test_conversation self.dispatcher.register_plugin(self.p) cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd_opts.get("strip_formatting") is True self.assertEqual(expected_response, output) def test_unignore_nonignored_channel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get("api_client")) self.assertFalse(self.dispatcher.unignore(c)) assert "testchannel" not in self.dispatcher.ignored_channels def test_ignore_duplicate_channel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get("api_client")) assert self.dispatcher.ignore(c) is True assert c.name in self.dispatcher.ignored_channels assert self.dispatcher.ignore(c) is False assert len(self.dispatcher.ignored_channels) == 1 def test_ignore_slackchannel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get("api_client")) c.name = "testchannel" assert self.dispatcher.ignore(c) is True assert "testchannel" in self.dispatcher.ignored_channels assert self.dispatcher._is_channel_ignored(self.p.abc, c) is True def test_unignore_slackchannel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get("api_client")) self.assertTrue(self.dispatcher.ignore(c)) self.assertTrue(self.dispatcher.unignore(c)) self.assertNotIn(test_channel.get("name"), self.dispatcher.ignored_channels) self.assertFalse(self.dispatcher._is_channel_ignored(self.p.abc, c)) @async_test async def test_push(self): self.dispatcher.register_plugin(self.p) self.test_payload["data"].update({"text": "!abc"}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == "!abc" assert output == "abcba" assert type(cmd_opts) == dict assert ("reply_in_thread" in list(cmd_opts.keys())) is True assert ("reply_broadcast" in list(cmd_opts.keys())) is True assert cmd_opts.get("reply_broadcast") is False assert cmd_opts.get("reply_in_thread") is False @async_test async def test_push_alias(self): self.dispatcher.register_plugin(self.p) self.test_payload["data"].update({"text": "!bca"}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == "!bca" assert output == "abcba" assert type(cmd_opts) == dict assert ("reply_in_thread" in list(cmd_opts.keys())) is True assert ("reply_broadcast" in list(cmd_opts.keys())) is True assert cmd_opts.get("reply_broadcast") is False assert cmd_opts.get("reply_in_thread") is False @async_test async def test_push_to_thread(self): self.dispatcher.register_plugin(self.p) self.test_payload["data"].update({"text": "!efg"}) e = SlackEvent(event_type="message", **self.test_payload) e.channel = test_conversation e.user = mock.Mock() cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == "!efg" assert output == "efgfe" assert type(cmd_opts) == dict assert ("reply_in_thread" in list(cmd_opts.keys())) is True assert ("reply_broadcast" in list(cmd_opts.keys())) is True assert cmd_opts.get("reply_broadcast") is False assert cmd_opts.get("reply_in_thread") is True @async_test async def test_push_to_thread_with_broadcast(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload["data"].update({"text": "!hij"}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == "!hij" assert output == "hijih" assert type(cmd_opts) == dict assert ("reply_in_thread" in list(cmd_opts.keys())) is True assert ("reply_broadcast" in list(cmd_opts.keys())) is True assert cmd_opts.get("reply_broadcast") is True assert cmd_opts.get("reply_in_thread") is True @async_test async def test_push_not_command(self): payload = dict(self.test_payload) payload["data"].update({"text": "Not a command"}) e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_no_text(self): payload = dict(self.test_payload) payload["data"].update({"text": ""}) e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_message_replied_event(self): payload = dict(self.test_payload) payload["data"].update({"subtype": "message_replied"}) e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_no_user(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload["data"].update({"subtype": "message_replied"}) payload["data"].pop("user") e = SlackEvent(event_type="message", **payload) assert await self.dispatcher.push(e) == (None, None, None) @async_test async def test_push_ignored_channel(self): c = SlackConversation(conversation=test_channel, api_client=test_payload.get("api_client")) self.dispatcher.ignore(c) self.dispatcher.register_plugin(self.p) self.dispatcher._is_channel_ignored = mock.Mock(return_value=True) self.test_payload["data"].update({ "text": "!abc", "user": test_user_id, "channel": test_channel_id }) e = SlackEvent(event_type="message", **self.test_payload) e.channel = test_conversation e.user = mock.Mock() assert await self.dispatcher.push(e) == ("_ignored_", "", None) @async_test async def test_async_cmd(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload["data"].update({"text": "!asyncabc"}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == "!asyncabc" assert output == "asyncabc response" assert type(cmd_opts) == dict assert ("reply_in_thread" in list(cmd_opts.keys())) is True assert ("reply_broadcast" in list(cmd_opts.keys())) is True assert ("parse" in list(cmd_opts.keys())) is True assert cmd_opts.get("reply_broadcast") is True assert cmd_opts.get("reply_in_thread") is True assert cmd_opts.get("parse") is None @async_test async def test_async_cmd_parse(self): self.dispatcher.register_plugin(self.p) payload = dict(self.test_payload) payload["data"].update({"text": "!asyncparse"}) e = SlackEvent(event_type="message", **self.test_payload) e.user = mock.Mock() e.channel = test_conversation cmd, output, cmd_opts = await self.dispatcher.push(e) assert cmd == "!asyncparse" assert output == "async parse command #parse" assert type(cmd_opts) == dict assert ("reply_in_thread" in list(cmd_opts.keys())) is True assert ("reply_broadcast" in list(cmd_opts.keys())) is True assert ("parse" in list(cmd_opts.keys())) is True assert cmd_opts.get("reply_broadcast") is False assert cmd_opts.get("reply_in_thread") is False assert cmd_opts.get("parse") is True