seratch / slack-edge

Slack app development framework for edge functions with streamlined TypeScript support
https://github.com/seratch/slack-edge-app-template
MIT License
87 stars 5 forks source link

Reacting app_mention and message events #21

Closed t6adev closed 5 months ago

t6adev commented 5 months ago

[UPDATED] This was my misunderstanding of how Slack sends events. I was confused if Slack catches a message then Slack sends one request that contains multiple events. In fact, Slack sends a request per event type, not per message 😥 https://api.slack.com/apis/connections/events-api#receiving-events


I wrote like this below. When a message has app_mention is received, not only A is reacted but also B.

app.event('app_mention', async ({ context, payload }) => {
  // Event A
});
app.event('message', async ({ context, payload }) => {
  // Event B
});

I can understand app_mention messages can be message but I'm feeling strange. Is it common sense or do I miss something? How can I complete the process at only A if the app_mention messages are received?

Thank you for your help.

seratch commented 5 months ago

Hi @t6adev, thanks again. This is because your app subscribes both app_mention and message events. Regardless whether your app subscribes app_mention events, message events delivers all visible message events to your app endpoint. If you want to skip the bot mentioned message events, you can check message.text string if it does not have the mention.

Let me close this issue now, but if you have further to ask, feel free to write in!

t6adev commented 5 months ago

Ok, thank you. Since the app.use (= postAuthorizeMiddleware) runs before handling events, I believe we can mark the mentioned message inside Cloudflare worker's fetch (it's messy😅)

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    ...
    const current = { isAppMention: false };
    app.use(async ({ body }) => {
      const slackRequestBody = body as SlackRequestBody;
      if (slackRequestBody.type === PayloadType.EventsAPI) {
        if (slackRequestBody.event?.type === 'app_mention') {
          current.isAppMention = true;
        }
      }
    });
    ...
  }
}

https://github.com/seratch/slack-edge/blob/2785568942b4bb2e10a38401ddbf8c7d7bdd8824/src/app.ts#L638-L647

seratch commented 5 months ago

Since the fetch handler can be invoked per request, your approach never works as you expect. In other words, your fetch function is always stateless (as long as you don't store the state in a database) so that your message listener never knows the current was set by a different app_mention request.

Alternatively, your message event listener can check if your app's bot user ID is mentioned in the message event. This is not specific to this slack-edge library. When you build a Slack app that subscribes both app_mention and message events, your code is responsible to handle these events.

If you need more assistance this, I am happy to help you in Japanese. Feel free to mention @seratch_ja (@seratch for English) on X. Since this is the issue tracker for managing this library's issues (bugs, enhancement ideas), I would like to stop discussing this here. It'd be appreciated if you could understand this.

t6adev commented 5 months ago

Thank you, I respect your opinion on how you manage this repo. (I also prefer to discuss something on the GitHub discussion page.)