LoginSignup
0
0

More than 1 year has passed since last update.

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

Posted at

サンプルコードの元: 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 パッケージを使って実装する必要がある

サンプル実装

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@slack/socket-mode のドキュメントに従えばいいです
(ちなみにこれらのドキュメントにたどり着くのが難しいのでnpmから辿ると探しやすいです。厳しい。)

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

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

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

  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を叩く必要がある

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

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

とりあえずこのissueコメントのとおりにやれば動くのでそのようにすると動く
これハマるとエラーメッセージがinvalid_authしか返ってこないのでしんどい


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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0