async def test_self_events(self):
        app = AsyncApp(client=self.web_client)
        app.event("reaction_added")(whats_up)

        self_event = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "type": "reaction_added",
                "user": "******",  # bot_user_id
                "item": {
                    "type": "message",
                    "channel": "C111",
                    "ts": "1599529504.000400",
                },
                "reaction": "heart_eyes",
                "item_user": "******",
                "event_ts": "1599616881.000800",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authed_users": ["W111"],
        }
        request = AsyncBoltRequest(body=self_event, mode="socket_mode")
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1
        await asyncio.sleep(1)  # wait a bit after auto ack()
        # The listener should not be executed
        assert self.mock_received_requests.get("/chat.postMessage") is None
Beispiel #2
0
    async def test_middleware_skip(self):
        app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret)
        app.event("app_mention", middleware=[skip_middleware])(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 404
        assert self.mock_received_requests["/auth.test"] == 1
Beispiel #3
0
    async def test_stable_auto_ack(self):
        app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,)
        app.event("reaction_added")(always_failing)

        for _ in range(10):
            request = self.build_valid_reaction_added_request()
            response = await app.async_dispatch(request)
            assert response.status == 200
Beispiel #4
0
    async def test_middleware_skip(self):
        app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret)
        app.event("app_mention", middleware=[skip_middleware])(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 404
        await assert_auth_test_count_async(self, 1)
    async def test_reaction_added(self):
        app = AsyncApp(client=self.web_client)
        app.event("reaction_added")(whats_up)

        request = self.build_valid_reaction_added_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
Beispiel #6
0
    async def test_app_mention(self):
        app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,)
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
 async def test_self_events_disabled(self):
     app = AsyncApp(client=self.web_client, ignoring_self_events_enabled=False)
     app.event("reaction_added")(whats_up)
     request = AsyncBoltRequest(body=self_event, mode="socket_mode")
     response = await app.async_dispatch(request)
     assert response.status == 200
     await assert_auth_test_count_async(self, 0)
     await asyncio.sleep(1)  # wait a bit after auto ack()
     # The listener should be executed
     assert self.mock_received_requests.get("/chat.postMessage") == 1
Beispiel #8
0
    async def test_process_before_response(self):
        app = AsyncApp(client=self.web_client, process_before_response=True,)
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1
        # no sleep here
        assert self.mock_received_requests["/chat.postMessage"] == 1
    async def test_bot_only_default_off(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            installation_store=BotOnlyMemoryInstallationStore(),
        )
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        with pytest.raises(ValueError):
            await app.async_dispatch(request)
Beispiel #10
0
    def test_events(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )

        async def event_handler():
            pass

        app.event("app_mention")(event_handler)

        input = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "client_msg_id": "9cbd4c5b-7ddf-4ede-b479-ad21fca66d63",
                "type": "app_mention",
                "text": "<@W111> Hi there!",
                "user": "******",
                "ts": "1595926230.009600",
                "team": "T111",
                "channel": "C111",
                "event_ts": "1595926230.009600",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1595926230,
            "authed_users": ["W111"],
        }
        timestamp, body = str(int(time())), json.dumps(input)

        async def endpoint(req: Request):
            return await app_handler.handle(req)

        api = Starlette(
            debug=True,
            routes=[
                Route("/slack/events", endpoint=endpoint, methods=["POST"])
            ],
        )
        app_handler = AsyncSlackRequestHandler(app)

        client = TestClient(api)
        response = client.post(
            "/slack/events",
            data=body,
            headers=self.build_headers(timestamp, body),
        )
        assert response.status_code == 200
        assert self.mock_received_requests["/auth.test"] == 1
Beispiel #11
0
    async def test_self_events(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            authorize=authorize,
        )
        app.event("reaction_added")(whats_up)

        self_event = {
            "token":
            "verification_token",
            "team_id":
            "T_SOURCE",
            "enterprise_id":
            "E_SOURCE",
            "api_app_id":
            "A111",
            "event": {
                "type": "reaction_added",
                "user": "******",  # bot_user_id
                "item": {
                    "type": "message",
                    "channel": "C111",
                    "ts": "1599529504.000400",
                },
                "reaction": "heart_eyes",
                "item_user": "******",
                "event_ts": "1599616881.000800",
            },
            "type":
            "event_callback",
            "event_id":
            "Ev111",
            "event_time":
            1599616881,
            "authorizations": [{
                "enterprise_id": "E_INSTALLED",
                "team_id": "T_INSTALLED",
                "user_id": "W111",
                "is_bot": True,
                "is_enterprise_install": False,
            }],
        }
        timestamp, body = str(int(time())), json.dumps(self_event)
        request = AsyncBoltRequest(body=body,
                                   headers=self.build_headers(timestamp, body))
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1
        await asyncio.sleep(1)  # wait a bit after auto ack()
        # The listener should not be executed
        assert self.mock_received_requests.get("/chat.postMessage") is None
    async def test_bot_only_oauth_flow(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            oauth_flow=AsyncOAuthFlow(settings=oauth_settings_bot_only),
        )
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
Beispiel #13
0
    async def test_process_before_response(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            authorize=authorize,
            process_before_response=True,
        )
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)
        # no sleep here
        assert self.mock_received_requests["/chat.postMessage"] == 1
    async def test_bot_only(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            installation_store=BotOnlyMemoryInstallationStore(),
            installation_store_bot_only=True,
        )
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
    async def test_bot_only_oauth_settings_conflicts(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            oauth_settings=oauth_settings,
            installation_store_bot_only=True,
        )
        app.event("app_mention")(whats_up)

        request = self.build_valid_app_mention_request()
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
    async def test_default(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        app.event("app_mention")(whats_up)

        timestamp, body = str(int(time())), json.dumps(app_mention_body)
        request = AsyncBoltRequest(
            body=body, headers=self.build_headers(timestamp, body)
        )
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
    async def test_events(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )

        async def event_handler():
            pass

        app.event("app_mention")(event_handler)

        input = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "client_msg_id": "9cbd4c5b-7ddf-4ede-b479-ad21fca66d63",
                "type": "app_mention",
                "text": "<@W111> Hi there!",
                "user": "******",
                "ts": "1595926230.009600",
                "team": "T111",
                "channel": "C111",
                "event_ts": "1595926230.009600",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1595926230,
            "authed_users": ["W111"],
        }
        timestamp, body = str(int(time())), json.dumps(input)

        api = Sanic(name=self.unique_sanic_app_name())
        app_handler = AsyncSlackRequestHandler(app)

        @api.post("/slack/events")
        async def endpoint(req: Request):
            return await app_handler.handle(req)

        _, response = await api.asgi_client.post(
            url="/slack/events",
            data=body,
            headers=self.build_headers(timestamp, body),
        )
        assert response.status_code == 200
        assert_auth_test_count(self, 1)
Beispiel #18
0
    async def test_simultaneous_requests(self):
        app = AsyncApp(client=self.web_client, signing_secret=self.signing_secret,)
        app.event("app_mention")(random_sleeper)

        request = self.build_valid_app_mention_request()

        times = 10
        tasks = []
        for i in range(times):
            tasks.append(asyncio.ensure_future(app.async_dispatch(request)))

        await asyncio.sleep(5)
        # Verifies all the tasks have been completed with 200 OK
        assert sum([t.result().status for t in tasks if t.done()]) == 200 * times

        assert self.mock_received_requests["/auth.test"] == times
        assert self.mock_received_requests["/chat.postMessage"] == times
    async def test_disabled(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            request_verification_enabled=False,
        )
        app.event("app_mention")(whats_up)

        # request including invalid headers
        expired = int(time()) - 3600
        timestamp, body = str(expired), json.dumps(app_mention_body)
        request = AsyncBoltRequest(
            body=body, headers=self.build_headers(timestamp, body)
        )
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)
        await asyncio.sleep(1)  # wait a bit after auto ack()
        assert self.mock_received_requests["/chat.postMessage"] == 1
Beispiel #20
0
    async def test_joined_left_events(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )
        app.event("reaction_added")(whats_up)

        join_event_body = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "type": "member_joined_channel",
                "user": "******",  # other user
                "channel": "C111",
                "channel_type": "C",
                "team": "T111",
                "inviter": "U222",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authed_users": ["W111"],
        }

        left_event_body = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "type": "member_left_channel",
                "user": "******",  # other user
                "channel": "C111",
                "channel_type": "C",
                "team": "T111",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authed_users": ["W111"],
        }

        @app.event("member_joined_channel")
        async def handle_member_joined_channel(say):
            await say("What's up?")

        @app.event("member_left_channel")
        async def handle_member_left_channel(say):
            await say("What's up?")

        timestamp, body = str(int(time())), json.dumps(join_event_body)
        request = AsyncBoltRequest(body=body,
                                   headers=self.build_headers(timestamp, body))
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1

        timestamp, body = str(int(time())), json.dumps(left_event_body)
        request = AsyncBoltRequest(body=body,
                                   headers=self.build_headers(timestamp, body))
        response = await app.async_dispatch(request)
        assert response.status == 200

        await asyncio.sleep(1)  # wait a bit after auto ack()
        # The listeners should be executed
        assert self.mock_received_requests.get("/chat.postMessage") == 2
Beispiel #21
0
class SlackTeam:
    def __init__(self, data: dict, slack: 'Slack'):
        self.slack = slack
        self.bot = self.slack.bot

        self.team_id = data['team_id']
        self.token = data['token']
        self.bot_id = data['bot_id']
        self.name = self.team_id

        self.app = AsyncApp(token=self.token)

        self.app.view("socket_modal_submission")(self.submission)
        self.app.event("message")(self.slack_message)
        self.app.event("member_joined_channel")(self.slack_member_joined)
        self.app.event("channel_left")(self.slack_channel_left)

        self.handler = AsyncSocketModeHandler(self.app, config.SLACK_APP_TOKEN)
        self.bot.loop.create_task(self.handler.start_async())

        self.bot.add_listener(self.on_message, 'on_message')
        self.bot.add_listener(self.on_raw_message_edit, 'on_raw_message_edit')
        self.bot.add_listener(self.on_raw_message_delete,
                              'on_raw_message_delete')

        self.channels: list[SlackChannel] = []
        self.members: list[SlackMember] = []

        self.slack.bot.loop.create_task(self.get_team_info())

        self.discord_messages: TTLCache[int,
                                        DiscordMessage] = TTLCache(ttl=600.0,
                                                                   maxsize=500)
        self.slack_messages: TTLCache[str,
                                      SlackMessage] = TTLCache(ttl=600.0,
                                                               maxsize=500)
        self.message_links = TTLCache(ttl=86400.0, maxsize=1000)

        self.initialize_data()
        self.messages_cached = asyncio.Event()
        self.members_cached = asyncio.Event()
        self.channels_cached = asyncio.Event()
        self.slack.bot.loop.create_task(self.cache_members())
        self.slack.bot.loop.create_task(self.cache_channels())
        self.slack.bot.loop.create_task(self.cache_messages())

    def initialize_data(self):
        """Initilises the data in the database if needed."""
        data = db.slack_bridge.find_one({'team_id': self.team_id})
        if not data:
            data = {
                'team_id': self.team_id,
                'aliases': [],
                'bridges': [],
                'tokens': {}
            }
            db.slack_bridge.insert_one(data)

    async def get_team_info(self):
        team_data = await self.app.client.team_info()
        self.name = team_data['team']['name']

    async def get_channels(self) -> list[dict]:
        """Function for getting channels, makes call to slack api and filters out channels bot isnt member of."""
        channels_data = await self.app.client.conversations_list(
            team_id=self.team_id)
        return [
            channel for channel in channels_data['channels']
            if channel['is_member']
        ]

    async def get_members(self) -> list[dict]:
        """Function for getting members, makes call to slack api and filters out bot accounts and slack bot account."""
        members_data = await self.app.client.users_list(team_id=self.team_id)
        return [
            member for member in members_data['members']
            if not member['is_bot'] and not member['id'] == 'USLACKBOT'
        ]

    async def add_user(self, user_id: str):
        user_data = await self.app.client.users_info(user=user_id)
        slack_member = SlackMember(user_data['user'], self.slack)
        await slack_member.get_discord_member()
        self.members[slack_member.team_id].append(slack_member)
        return slack_member

    def get_user(self,
                 slack_id: str = None,
                 *,
                 discord_id: int = None) -> Optional[SlackMember]:
        """Get SlackMember via slack id or discord id."""
        for member in self.members:
            if (slack_id is not None and member.id == slack_id) or \
               (discord_id is not None and member.discord_member and member.discord_member.id == discord_id):
                return member

    def get_channel(self,
                    slack_id: str = None,
                    *,
                    discord_id: int = None) -> Optional[SlackChannel]:
        """Get SlackChannel via slack id or discord id."""
        for channel in self.channels:
            if (slack_id is not None and channel.id == slack_id) or \
               (discord_id is not None and channel.discord_channel and channel.discord_channel.id == discord_id):
                return channel

    async def cache_messages(self):
        """Cache messages in the database."""
        await self.members_cached.wait()
        await self.channels_cached.wait()

        messages = db.slack_messages.find({
            'team_id': self.team_id
        }).sort('timestamp', 1)
        for message in messages:
            twenty_four_hours = 24 * 60 * 60
            if time.time() - message['timestamp'] > twenty_four_hours:
                db.slack_messages.delete_one(message)
                continue

            if message['origin'] == 'discord':
                self.message_links[message['discord_message_id']] = message[
                    'slack_message_id']
            elif message['origin'] == 'slack':
                self.message_links[message['slack_message_id']] = message[
                    'discord_message_id']

        self.messages_cached.set()
        self.slack.bot.logger.debug(
            f'{len(self.message_links)} Slack and Discord messages cached for team [{self.team_id}]'
        )

    async def cache_channels(self):
        """Caches channels."""
        channels = await self.get_channels()
        for channel_data in channels:
            if self.get_channel(channel_data['id']):
                continue

            channel = SlackChannel(
                team=self,
                channel_id=channel_data['id'],
                slack=self.slack,
            )
            self.channels.append(channel)

        self.channels_cached.set()
        self.slack.bot.logger.debug(
            f'{len(channels)} Slack channels cached for team [{self.team_id}]')

    async def cache_members(self):
        """Caches members."""
        members = await self.get_members()
        for member_data in members:
            if self.get_user(member_data['id']):
                continue

            member = SlackMember(
                data=member_data,
                slack=self.slack,
            )
            self.slack.bot.loop.create_task(member.get_discord_member())
            self.members.append(member)

        self.members_cached.set()
        self.slack.bot.logger.debug(
            f'{len(members)} Slack member cached for team [{self.team_id}]')

    async def delete_discord_message(self,
                                     channel_id: int,
                                     message_id: int,
                                     *,
                                     ts: str = None):
        await self.slack.bot.http.delete_message(channel_id, message_id)

        if ts in self.slack_messages:
            del self.slack_messages[ts]

        db.slack_messages.delete_one({'slack_message_id': ts})

    async def delete_slack_message(self,
                                   message_id: str,
                                   discord_channel_id: int,
                                   *,
                                   discord_message_id: int = None):
        slack_channel = self.get_channel(discord_id=discord_channel_id)

        await self.app.client.chat_delete(channel=slack_channel.id,
                                          ts=message_id)
        if discord_message_id in self.discord_messages:
            del self.discord_messages[discord_message_id]

        db.slack_messages.delete_one(
            {'discord_message_id': discord_message_id})

    async def get_slack_message(
            self,
            channel_id: str,
            message_id: str,
            discord_message_id: int = None) -> Optional[SlackMessage]:
        if message_id is None:
            return

        result = await self.app.client.conversations_history(
            channel=channel_id, inclusive=True, oldest=message_id, limit=1)
        if not result or not result['messages']:
            return

        message = result['messages'][0]
        data = {
            'event': {
                'team_id':
                message['team_id'],
                'user':
                message['user'] if 'user' in message else message['username'],
                'discord_message_id':
                discord_message_id,
                'channel':
                channel_id,
                'text':
                message['text'],
                'ts':
                message_id,
                'files': [],
                'subtype':
                ''
            }
        }
        return SlackMessage(data, self.slack)

    async def get_discord_message(
            self,
            channel_id: int,
            message_id: int,
            slack_message_id: str = None) -> Optional[DiscordMessage]:
        channel = self.slack.bot.get_channel(channel_id)

        try:
            message = await channel.fetch_message(message_id)
        except:
            # most-likely errors when message has been deleted
            db.slack_messages.delete_one({'discord_message_id': message_id})
            return

        if message:
            discord_message = DiscordMessage(message, self.slack)
            discord_message.slack_message_id = slack_message_id
            return discord_message
        else:
            db.slack_messages.delete_one({'discord_message_id': message_id})

    async def submission(self, ack):
        """Function that acknowledges events."""
        await ack()

    async def slack_channel_left(self, body: dict):
        """Function called when bot leaves a channel"""
        event = body['event']
        channel_id = event['channel']
        channel = self.get_channel(channel_id)
        if channel:
            db.slack_bridge.update_one(
                {'team_id': self.team_id},
                {'$pull': {
                    'bridges': {
                        'slack_channel_id': channel_id
                    }
                }})
            self.channels.remove(channel)

    async def slack_member_joined(self, body: dict):
        event = body['event']
        channel_id = event['channel']
        user_id = event['user']
        if user_id == self.bot_id:
            channel = SlackChannel(self, channel_id, self.slack)
            self.channels.append(channel)
        else:
            user_data = await self.app.client.users_info(user=user_id)
            member = SlackMember(user_data['user'], self.slack)
            self.members.append(member)

    async def handle_delete_message(self, body: dict):
        event = body['event']

        ts = event['deleted_ts']
        channel_id = event['channel']

        slack_message = self.slack_messages.get(ts, None)
        slack_message_link = self.message_links.get(ts, None)

        if not slack_message:
            slack_channel = self.get_channel(slack_id=channel_id)
            if not slack_channel.discord_channel or not slack_message_link:
                return
            return await self.delete_discord_message(
                slack_channel.discord_channel.id, slack_message_link, ts=ts)

        return await slack_message.delete()

    async def handle_edit_message(self, body: dict):
        event = body['event']

        ts = event['message']['ts']
        channel_id = event['channel']

        # check if message was edited by the bot
        edit_message = next(
            filter(lambda dm: dm.slack_message_id == ts,
                   self.discord_messages.values()), None)
        if edit_message:
            return

        slack_message = self.slack_messages.get(ts, None)
        if not slack_message:
            slack_message_link = self.message_links[
                ts] if ts in self.message_links else None
            slack_message = await self.get_slack_message(
                channel_id, ts, slack_message_link)

        if slack_message:
            slack_message.text = event['message']['text']
            asyncio.create_task(slack_message.send_to_discord(edit=True))

    async def slack_message(self, body):
        """Function called on message even from slack."""
        await self.messages_cached.wait()

        event = body['event']
        is_delete = 'subtype' in body['event'] and body['event'][
            'subtype'] == 'message_deleted'
        is_edit = 'subtype' in body['event'] and body['event'][
            'subtype'] == 'message_changed'
        is_bot_message = 'subtype' in body['event'] and body['event'][
            'subtype'] == 'bot_message'

        if is_edit:
            return await self.handle_edit_message(event)
        if is_delete:
            return await self.handle_delete_message(event)

        if is_bot_message:
            return

        message = SlackMessage(body, self.slack)
        asyncio.create_task(message.send_to_discord())

    # Discord events

    async def on_raw_message_delete(self,
                                    payload: discord.RawMessageDeleteEvent):
        channel_id = payload.channel_id

        slack_channel = self.get_channel(discord_id=channel_id)
        if not slack_channel:
            return

        team = slack_channel.team
        await team.messages_cached.wait()

        message_id = payload.message_id
        discord_message = team.discord_messages.get(message_id, None)
        if not discord_message:
            discord_message_link = team.message_links[message_id]
            return await team.delete_slack_message(
                discord_message_link,
                channel_id,
                discord_message_id=message_id)

        await discord_message.delete()

    async def on_raw_message_edit(self,
                                  payload: discord.RawMessageUpdateEvent):
        """
        Function called on on_edit_message event, used for dealing with message edit events on the discord side
        and doing the same on the slack end.
        """
        if 'content' not in payload.data:
            return

        channel_id = payload.channel_id

        slack_channel = self.get_channel(discord_id=channel_id)
        if not slack_channel:
            return

        team = slack_channel.team
        await team.messages_cached.wait()

        message_id = payload.message_id
        content = payload.data['content']
        cached_message = team.discord_messages.get(message_id, None)
        if not cached_message:
            cached_message_link = team.message_links.get(message_id, None)
            cached_message = await team.get_discord_message(
                channel_id, message_id, cached_message_link)
            if cached_message is None:
                return

        cached_message.text = content
        await cached_message.send_to_slack(edit=True)

    async def on_message(self, message: discord.Message):
        """Function call on on_message event, used for identifying discord bridge channel and forwarding the messages to slack."""
        # ignore webhook messages and pms
        if not message.guild or message.webhook_id:
            return

        slack_channel = self.get_channel(discord_id=message.channel.id)
        if not slack_channel:
            return

        await self.messages_cached.wait()

        discord_message = DiscordMessage(message, self.slack)
        await discord_message.send_to_slack()
Beispiel #22
0
    async def test_invalid_message_events(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
        )

        async def handle():
            pass

        # valid
        app.event("message")(handle)

        with pytest.raises(ValueError):
            app.event("message.channels")(handle)
        with pytest.raises(ValueError):
            app.event("message.groups")(handle)
        with pytest.raises(ValueError):
            app.event("message.im")(handle)
        with pytest.raises(ValueError):
            app.event("message.mpim")(handle)

        with pytest.raises(ValueError):
            app.event(re.compile("message\\..*"))(handle)

        with pytest.raises(ValueError):
            app.event({"type": "message.channels"})(handle)
        with pytest.raises(ValueError):
            app.event({"type": re.compile("message\\..*")})(handle)
Beispiel #23
0
    async def test_self_joined_left_events(self):
        app = AsyncApp(
            client=self.web_client,
            signing_secret=self.signing_secret,
            authorize=authorize,
        )
        app.event("reaction_added")(whats_up)

        join_event_body = {
            "token": "verification_token",
            "team_id": "T_SOURCE",
            "enterprise_id": "E_SOURCE",
            "api_app_id": "A111",
            "event": {
                "type": "member_joined_channel",
                "user": "******",  # bot_user_id
                "channel": "C111",
                "channel_type": "C",
                "team": "T_INSTALLED",
                "inviter": "U222",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authorizations": [
                {
                    "enterprise_id": "E_INSTALLED",
                    "team_id": "T_INSTALLED",
                    "user_id": "W111",
                    "is_bot": True,
                    "is_enterprise_install": False,
                }
            ],
        }

        left_event_body = {
            "token": "verification_token",
            "team_id": "T_SOURCE",
            "enterprise_id": "E_SOURCE",
            "api_app_id": "A111",
            "event": {
                "type": "member_left_channel",
                "user": "******",  # bot_user_id
                "channel": "C111",
                "channel_type": "C",
                "team": "T_INSTALLED",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authorizations": [
                {
                    "enterprise_id": "E_INSTALLED",
                    "team_id": "T_INSTALLED",
                    "user_id": "W111",
                    "is_bot": True,
                    "is_enterprise_install": False,
                }
            ],
        }

        @app.event("member_joined_channel")
        async def handle_member_joined_channel(say):
            await say("What's up?")

        @app.event("member_left_channel")
        async def handle_member_left_channel(say):
            await say("What's up?")

        timestamp, body = str(int(time())), json.dumps(join_event_body)
        request = AsyncBoltRequest(
            body=body, headers=self.build_headers(timestamp, body)
        )
        response = await app.async_dispatch(request)
        assert response.status == 200
        await assert_auth_test_count_async(self, 1)

        timestamp, body = str(int(time())), json.dumps(left_event_body)
        request = AsyncBoltRequest(
            body=body, headers=self.build_headers(timestamp, body)
        )
        response = await app.async_dispatch(request)
        assert response.status == 200

        await asyncio.sleep(1)  # wait a bit after auto ack()
        # The listeners should be executed
        assert self.mock_received_requests.get("/chat.postMessage") == 2
    async def test_self_joined_left_events(self):
        app = AsyncApp(client=self.web_client)
        app.event("reaction_added")(whats_up)

        join_event_body = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "type": "member_joined_channel",
                "user": "******",  # bot_user_id
                "channel": "C111",
                "channel_type": "C",
                "team": "T111",
                "inviter": "U222",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authed_users": ["W111"],
        }

        left_event_body = {
            "token": "verification_token",
            "team_id": "T111",
            "enterprise_id": "E111",
            "api_app_id": "A111",
            "event": {
                "type": "member_left_channel",
                "user": "******",  # bot_user_id
                "channel": "C111",
                "channel_type": "C",
                "team": "T111",
            },
            "type": "event_callback",
            "event_id": "Ev111",
            "event_time": 1599616881,
            "authed_users": ["W111"],
        }

        @app.event("member_joined_channel")
        async def handle_member_joined_channel(say):
            await say("What's up?")

        @app.event("member_left_channel")
        async def handle_member_left_channel(say):
            await say("What's up?")

        request = AsyncBoltRequest(body=join_event_body, mode="socket_mode")
        response = await app.async_dispatch(request)
        assert response.status == 200
        assert self.mock_received_requests["/auth.test"] == 1

        request = AsyncBoltRequest(body=left_event_body, mode="socket_mode")
        response = await app.async_dispatch(request)
        assert response.status == 200

        await asyncio.sleep(1)  # wait a bit after auto ack()
        # The listeners should be executed
        assert self.mock_received_requests.get("/chat.postMessage") == 2