def test_get_message(self, client: SlackApiClient, cid: str, payload: dict, expected: Union[None, Message]): """Tests SlackApiClient.get_message""" with responses.RequestsMock() as rm: ts = '1581947248' api = f'{URL}/conversations.history?channel={cid}&oldest={ts}&latest={ts}&inclusive=true&limit=1' rm.add('GET', api, body=json.dumps(payload)) if not payload['ok']: rm.add('POST', f'{URL}/chat.postMessage') assert client.get_message(Conversation(id=cid, name='test'), ts) == expected assert 'Authorization' in rm.calls[0].request.headers # Should be from cache, because we in a requests mock context, if we hit the API again the test wil fail # with a connection issue assert client.get_message(Conversation(id=cid, name='test'), ts) == expected
def get_channel(self, channel_id) -> Optional[Conversation]: """ https://api.slack.com/methods/conversations.info :param channel_id: The id of the Channel to locate :return: A Conversation object if the channel is found, else None """ return cache.get_or_set( key=Conversation.create_key(channel_id), default=lambda: self.__get(Conversation, 'conversations.info', 'channel', channel=channel_id) )
def test_create_with_list(self): data = [{ 'id': 'asdf', 'name': 'foobar' }, '{"id": "asdf2", "name": "foobar2"}'] convos = Conversation.create(data) self.assertIsInstance(convos, list) self.assertEqual('asdf', convos[0].id) self.assertEqual('foobar', convos[0].name) self.assertEqual('asdf2', convos[1].id) self.assertEqual('foobar2', convos[1].name)
def test_post_message(self, client: SlackApiClient): """Tests SlackApiClient.post_message""" with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.postMessage') client.post_message(Conversation(id='test', name='test'), 'message') assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'text': 'message' }
def test_delete_message(self, client: SlackApiClient): """Tests SlackApiClient.delete_message""" with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.delete') client.delete_message( Conversation(id='test', name='test'), Message(user='******', text='I never test mah code', ts='12345.67890')) assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'ts': '12345.67890' }
def test_post_image(self, client: SlackApiClient): with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.postMessage') client.post_image(Conversation(id='test', name='test'), 'http://i.imgflip.com/blah.jpg', 'Image') assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'blocks': [{ "type": "image", "image_url": 'http://i.imgflip.com/blah.jpg', "alt_text": "Image" }] }
def process_from_cli(data): text = data['message'] if not text.startswith(settings.FRISKY_PREFIX): text = f'{settings.FRISKY_PREFIX}{text}' message = MessageEvent( username=data['username'], channel_name=data['channel'], text=text, ) conversation = Conversation( id=data['channel'], name=data['channel'], is_channel=True, ) for reply in frisky.handle_message_synchronously(message): if reply is not None: slack_api_client.post_message(conversation, reply)
def test_create_with_none(self): convo = Conversation.create(None) self.assertIsNone(convo)
def test_create_with_string(self): convo = Conversation.create('{"id": "asdf", "name": "foobar"}') self.assertEqual('asdf', convo.id) self.assertEqual('foobar', convo.name)
def test_create_with_dict(self): convo = Conversation.create({'id': 'asdf', 'name': 'foobar'}) self.assertEqual('asdf', convo.id) self.assertEqual('foobar', convo.name)
def process_event(data): slack_api_client = SlackApiClient(settings.SLACK_ACCESS_TOKEN) # noinspection PyBroadException try: if data['event'].get('subtype') in SUBTYPE_BLACKLIST: logger.debug(f'Ignoring {data["event"]["event_id"]}, subtype was in blacklist') return event_wrapper: Event = Event.from_dict(data) event = event_wrapper.get_event() # team = slack_api_client.get_workspace(data['team_id']) frisky = Frisky( name=settings.FRISKY_NAME, prefix=settings.FRISKY_PREFIX, ignored_channels=settings.FRISKY_IGNORED_CHANNELS, ) if isinstance(event, ReactionAdded): user = slack_api_client.get_user(event.user) channel = slack_api_client.get_channel(event.item.channel) item_user = slack_api_client.get_user(event.item_user) added = event.type == 'reaction_added' message = slack_api_client.get_message(channel, event.item.ts) frisky.handle_reaction( ReactionEvent( emoji=event.reaction, username=user.get_short_name(), added=added, message=MessageEvent( username=item_user.get_short_name(), channel_name=channel.name, text=message.text, command='', args=tuple(), ), ), reply_channel=lambda reply: slack_api_client.post_message(channel, reply) ) elif isinstance(event, MessageSent): user = slack_api_client.get_user(event.user) if event.channel_type == 'im': # TODO: Is there an api method (or a reason) to look this up? channel = Conversation(id=event.channel, name=user.name) elif event.channel_type == 'channel': channel = slack_api_client.get_channel(event.channel) else: return frisky.handle_message( MessageEvent( username=user.get_short_name(), channel_name=channel.name, text=event.text, command='', args=tuple(), ), reply_channel=lambda res: reply(slack_api_client, channel, res) ) except KeyError as err: stacktrace = traceback.format_exc() slack_api_client.emergency_log(stacktrace) slack_api_client.emergency_log(f'Trouble deserializing this event:\n{str(data)}') logger.warning('KeyError thrown deserializing event', exc_info=err) except Exception as err: stacktrace = traceback.format_exc() log_message = f'{stacktrace}\nCaused by:\n{str(data)}' slack_api_client.emergency_log(log_message) logger.warning('General exception thrown handling event', exc_info=err)
class TestClient: @pytest.fixture() def client(self) -> SlackApiClient: yield SlackApiClient('test-token') @pytest.mark.parametrize('cid, payload, expected', [ ('test_ok', { 'ok': True, 'messages': [{ 'user': '******', 'text': 'Im great', 'ts': '1581947248' }] }, Message(user='******', text='Im great', ts='1581947248')), ('test_not_ok', { 'ok': False }, None), ]) @pytest.mark.django_db def test_get_message(self, client: SlackApiClient, cid: str, payload: dict, expected: Union[None, Message]): """Tests SlackApiClient.get_message""" with responses.RequestsMock() as rm: ts = '1581947248' api = f'{URL}/conversations.history?channel={cid}&oldest={ts}&latest={ts}&inclusive=true&limit=1' rm.add('GET', api, body=json.dumps(payload)) if not payload['ok']: rm.add('POST', f'{URL}/chat.postMessage') assert client.get_message(Conversation(id=cid, name='test'), ts) == expected assert 'Authorization' in rm.calls[0].request.headers # Should be from cache, because we in a requests mock context, if we hit the API again the test wil fail # with a connection issue assert client.get_message(Conversation(id=cid, name='test'), ts) == expected @pytest.mark.parametrize('uid, payload, expected', [ ('test_ok', USER_OK, USER_OK_MODEL), ('test_not_ok', '{"ok": false}', None), ]) @pytest.mark.django_db def test_get_user(self, client: SlackApiClient, uid: str, payload: str, expected: Union[None, Message]): """Tests SlackApiClient.get_user""" with responses.RequestsMock() as rm: rm.add('GET', f'{URL}/users.info?user={uid}', body=payload) if not json.loads(payload)['ok']: rm.add('POST', f'{URL}/chat.postMessage') assert client.get_user(uid) == expected assert 'Authorization' in rm.calls[0].request.headers # Should be from cache, because we in a requests mock context, if we hit the API again the test wil fail # with a connection issue assert client.get_user(uid) == expected @pytest.mark.parametrize('cid, payload, expected', [ ('test_ok', { 'ok': True, 'channel': { 'id': 'test_ok', 'name': 'test' } }, Conversation(id='test_ok', name='test')), ('test_not_ok', { 'ok': False }, None), ]) @pytest.mark.django_db def test_get_channel(self, client: SlackApiClient, cid: str, payload: dict, expected: Union[None, Message]): """Tests SlackApiClient.get_channel""" with responses.RequestsMock() as rm: rm.add('GET', f'{URL}/conversations.info?channel={cid}', body=json.dumps(payload)) if not payload['ok']: rm.add('POST', f'{URL}/chat.postMessage') assert client.get_channel(cid) == expected assert 'Authorization' in rm.calls[0].request.headers # Should be from cache, because we in a requests mock context, if we hit the API again the test wil fail # with a connection issue assert client.get_channel(cid) == expected @pytest.mark.parametrize('tid, payload, expected', [ ('test_ok', { 'ok': True, 'team': { 'id': 'test_ok', 'name': 'test', 'domain': '502nerds.com' } }, Team(id='test_ok', name='test', domain='502nerds.com')), ('test_not_ok', { 'ok': False }, None), ]) @pytest.mark.django_db def test_get_team(self, client: SlackApiClient, tid: str, payload: dict, expected: Union[None, Message]): """Tests SlackApiClient.get_team""" with responses.RequestsMock() as rm: rm.add('GET', f'{URL}/team.info?team={tid}', body=json.dumps(payload)) if not payload['ok']: rm.add('POST', f'{URL}/chat.postMessage') assert client.get_workspace(tid) == expected assert 'Authorization' in rm.calls[0].request.headers # Should be from cache, because we in a requests mock context, if we hit the API again the test wil fail # with a connection issue assert client.get_workspace(tid) == expected @pytest.mark.django_db def test_post_message(self, client: SlackApiClient): """Tests SlackApiClient.post_message""" with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.postMessage') client.post_message(Conversation(id='test', name='test'), 'message') assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'text': 'message' } @pytest.mark.django_db def test_update_message(self, client: SlackApiClient): """Tests SlackApiClient.update_message""" with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.update') client.update_message(Conversation(id='test', name='test'), Message(user='******', text='I never test mah code', ts='12345.67890'), text='I always test mah code') assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'text': 'I always test mah code', 'ts': '12345.67890' } @pytest.mark.django_db def test_delete_message(self, client: SlackApiClient): """Tests SlackApiClient.delete_message""" with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.delete') client.delete_message( Conversation(id='test', name='test'), Message(user='******', text='I never test mah code', ts='12345.67890')) assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'ts': '12345.67890' } @pytest.mark.django_db def test_post_image(self, client: SlackApiClient): with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.postMessage') client.post_image(Conversation(id='test', name='test'), 'http://i.imgflip.com/blah.jpg', 'Image') assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == { 'channel': 'test', 'blocks': [{ "type": "image", "image_url": 'http://i.imgflip.com/blah.jpg', "alt_text": "Image" }] } @pytest.mark.django_db def test_post_emergency_log(self, client: SlackApiClient): """Tests SlackApiClient.emergency_log""" with responses.RequestsMock() as rm: rm.add('POST', f'{URL}/chat.postMessage') client.emergency_log('F**K') expected = { 'channel': settings.FRISKY_LOGGING_CHANNEL, 'text': '```F**K```' } assert 'Authorization' in rm.calls[0].request.headers assert json.loads(rm.calls[0].request.body) == expected
def test_dm_deserialization(self): convo = Conversation.from_json(dm_json) self.assertIsNotNone(convo) self.assertIsNone(convo.name) self.assertTrue(convo.is_im)