SlackのEvent APIやSocket Modeのドキュメント見てもわかりにくかったところを雑多にメモる

サンプルコードの元: https://github.com/sisisin-sandbox/try-socket-mode/blob/master/src/index.ts

# Expressを使ってSlackのOAuthフローをしつつSocket Modeを利用する

boltでSocketModeReceiverを使ってOAuthフローを実装するまでは出来るが、そこにユーザー定義のエンドポイントを足す事ができない（SocketModeReceiverとExpressReceiverを同時に使えない）ため、もしそのようなことがしたい場合は `@slack/oauth` と `@slack/socket-mode` パッケージを使って実装する必要がある

サンプル実装

```typescript:index.ts
import { InstallProvider } from '@slack/oauth';
import { SocketModeClient } from '@slack/socket-mode';
import express from 'express';
import fs from 'fs';
import https from 'https';

const app = express();
const server = https.createServer(
  { key: fs.readFileSync(process.env.PRIV_KEY!, 'utf-8'), cert: fs.readFileSync(process.env.CERT!, 'utf-8') },
  app,
);
const socketClient = new SocketModeClient({ appToken: process.env.SLACK_APP_TOKEN! });

const installer = new InstallProvider({
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
  stateSecret: 'my-state-secret',
});

app.get('/slack/install', async (req, res, next) => {
  const url = await installer.generateInstallUrl({
    scopes: [],
    userScopes: ['channels:read', 'channels:history', 'im:history'],
  });

  res.send(
    `<a href=${url}><img alt=""Add to Slack"" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x" /></a>`,
  );
});
app.get('/slack/oauth_redirect', async (req, res) => {
  await installer.handleCallback(req, res, {
    success: (installation, options, callbackReq, callbackRes) => {
      if ((callbackReq as any).session) {
        (callbackReq as any).session.slack = installation;
      }
      (callbackRes as any).redirect('/');
    },
  });
});
app.get('/', (req, res) => {
  res.send('ok');
});
socketClient.on('message', (event) => {
  event.ack();
  console.log(event.event.text);
});

async function main() {
  server.listen(process.env.PORT || 3000, () => {
    console.log(`server running`);
  });

  await socketClient.start();
}
main().catch((err) => console.error(err));
```

基本的に [@slack/oauth](https://slack.dev/node-slack-sdk/oauth) と [@slack/socket-mode](https://slack.dev/node-slack-sdk/socket-mode) のドキュメントに従えばいいです
（ちなみにこれらのドキュメントにたどり着くのが難しいのでnpmから辿ると探しやすいです。厳しい。）

expressを使う場合、セッションをexpress-sessionなどを使ってexpress側に持たせる事が多いと思う
その場合、ユーザーごとの `installation` 情報はサンプル実装の `installer.handleCallback()`  呼び出しの部分にあるように、sessionに持たせる形になる
セッションでSlackのtokenをもたせるので、ドキュメントにあるような `InstallProvider` で `installationStore` を実装する必要はない（warnが出るので若干気持ち悪いが


# oauthで認可を得たユーザーの権限でevent apiのイベントを受け取る方法

上記サンプルコード内の↓の部分のように、 `userScope` にて権限を設定すると出来る
至極基本的なことのはずなのにドキュメントの記載が見つけられなくてこれを発見するのに大変苦労した・・・
（見つけたのは確かpythonのサンプルコードでuserScopeを指定してる場所があっておや、と思ったとかだった。リンク失念）

```typescript
  const url = await installer.generateInstallUrl({
    scopes: [],
    userScopes: ['channels:read', 'channels:history', 'im:history'],
  });
```

# apps.event.authorizations.listを素直に叩くとinvalid_authが出る

botでは受け取れないユーザー固有のイベント（DMの受信など）を受け取るようなアプリを書く場合、EventAPIによって飛んできたEventが「どのユーザーに見せるべきか」を判断するために [apps.event.authorizations.list](https://api.slack.com/methods/apps.event.authorizations.list)を叩く必要がある

さて@slack/boltや@slack/web-apiを普通に使って以下のように取得しようとすると　`invalid_auth` になってしまう

```ts
app.event('message', async({client,body, event})=>{
  await client.apps.event.authorizations.list({...})
})
const webClient = new WebClient(token)
webClient.apps.event.authorizations.list({...})
```

とりあえず[このissueコメント](https://github.com/slackapi/node-slack-sdk/issues/1149#issuecomment-756290310)のとおりにやれば動くのでそのようにすると動く
これハマるとエラーメッセージがinvalid_authしか返ってこないのでしんどい


---

以上雑多な感じにメモしました
slackのドキュメント、充実してる気がするんだけど欲しい情報に辿り着きにくかったり、エラーが出たりしたときにどうすれば対処できるのかが分かりにくかったりで凝ったことやろうとすると結構しんどい・・・