【Slack のソケットモードを使った Bot開発】 Slack からの OBS操作（シーン切り替え）を実装してみる

この記事では、以下の @seratch さんが書かれた記事の内容を試して、さらにその後にやったこと（OBS連携の追加実装）などを書いています。

●Slack ソケットモードの最も簡単な始め方 - Qiita
　https://qiita.com/seratch/items/1a460c08c3e245b56441

## Slack ソケットモードを最も簡単に始める
まずは、[上記の Qiita の記事](https://qiita.com/seratch/items/1a460c08c3e245b56441)をそのままなぞっていきますが、その前に上記の記事から少し情報を転記して補足します。

### Slack ソケットモードとは？
[冒頭の記事](https://qiita.com/seratch/items/1a460c08c3e245b56441)からの一部引用ですが、「2020年年のベータ期間を経て 2021年1月12日（米国時間）に正式リリースとなった機能」とのことです。

![ソケットモードとは.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/197a1f93-6456-e77c-5de3-ebbdad3ce53a.png)

何が嬉しいか、という部分も情報を引用しつつ補足します。

![ソケットモードの補足の続き.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/401459ab-c4e5-a6e4-701c-d64ceea6988a.png)

今回、試そうとしている Bot開発などで、インターネット側からアクセスできるエンドポイントを準備する（サーバとして動作するものを準備し、グローバル側からアクセスできる何らかの対応をする）ということを行うことなく、簡単に開発を進められるものであるようです。

ローカルで動かしているサーバをインターネットからアクセスできるようにするために、[ngrok](https://ngrok.com/) といったサービスを使う手段もありますが（※ Bot開発のハンズオンイベントに参加すると良く活用されていたり）、それが不要になるので、手間の削減やネットワーク的な制約がある環境下での Bot 運用なども行うことができそうです。

元の記事にいろいろな情報が書かれてますので、詳細はそちらをご覧ください。

### 参考記事の内容をなぞっていく
ここでは、とりあえず[冒頭の記事](https://qiita.com/seratch/items/1a460c08c3e245b56441)の内容をそのまま進めていきます。
プログラムを書く部分は複数のものが提示されていますが、自分は Node.js（JavaScript）で試しました。

元の記事に、キャプチャ画像をまじえた分かりやすい説明が書かれているので、その内容を見て以下の設定・作業を行ってください。

* Slackアプリの作成
* ソケットモードの設定（ここで、SLACK_APP_TOKEN を取得）
* グローバルショートカットの設定
* イベントAPI の設定
* ボットユーザーの設定
* アプリをワークスペースにインストール（ここで、SLACK_BOT_TOKEN を取得）

そして、元ページにサンプルコードが言語違いで 4種類あるので、その中の好きなものを選んで試してください。

自分は [JavaScript のサンプル](https://qiita.com/seratch/items/1a460c08c3e245b56441#javascript-%E3%81%A7%E5%A7%8B%E3%82%81%E3%82%8B)を使いました。
npmコマンドを使って下準備をし、JavaScript のサンプルコードを準備します（※ サンプル内の SLACK_APP_TOKEN、SLACK_BOT_TOKEN は、ご自身が取得されたものを環境変数経由で渡すなり、とりあえずテスト用にソースに書いてしまうなど、なんらか対応を行ってください）。

あとは、nodeコマンドでプログラムを実行し、そのままの状態にしておいてください。

ここまでの準備が整ったら、Slackアプリで以下を試してみましょう。

* アプリをインストールした Slack のワークスペースで、作成したボットユーザーを任意のチャンネルに招待 ⇒ チャンネルで「こんにちは」と投稿
* 作成したグローバルショートカットを実行する

自分で実際に試してみた結果は、以下のツイートのとおりとなりました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Slack のソケットモードを早速、Qiita の記事の内容そのままで試してみた。<br><br>アクセス可能なエンドポイントを準備するようなこともなく、Node.jsでサンプルのプログラムをコマンド実行する感じで、<br>Slack 上にグローバルショートカットを追加したり、応答する Bot を追加したりできてしまった。 <a href="https://t.co/t2BZxMPDIm">https://t.co/t2BZxMPDIm</a> <a href="https://t.co/WbQxsd3p3G">pic.twitter.com/WbQxsd3p3G</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1349654496075345920?ref_src=twsrc%5Etfw">January 14, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これは便利すぎる！

## Bot の応答の部分のみに最小化
ここから、グローバルショートカットの部分は用いず、Bot絡みの部分のみを使っていこうと思います。

その下準備として、サンプルコードの中で必要そうな部分のみが残るようにしてみました。

```JavaScript
const { App } = require('@slack/bolt');

const app = new App({
  socketMode: true,
  token: "【Botのトークン（SLACK_BOT_TOKEN）】",
  appToken: "【アプリのトークン（SLACK_APP_TOKEN）】"
});

app.message("こんにちは", async ({ message, say }) => {
  await say(`:wave: こんにちは <@${message.user}>！`);
});

(async () => {
  await app.start();
  console.log('⚡️ Bolt app started');
})();
```

内容をこれだけにしてみた後、このプログラムを実行してみて、Slackアプリ上で Bot の応答が動作するか確認します。先ほどと同じく、「こんにちは」と投稿された内容に応答が返ってくれば OK です。

## OBS のシーン切り替え機能を追加実装する
さらに、Slackアプリ上でキーワードを入力したら、別サービス・別アプリと連携した何らかの動作が行われるものを作ってみます。

ここでは、映像のライブ配信などで用いられたりする [OBS](https://obsproject.com/ja) を組み合わせます。
以前、この OBS の操作を外部から行う仕組みを試したことがあり、そのノウハウを活用してみました（以下が、その時に書いた記事の一部です）。

●Node-RED を使って OBS を遠隔操作してみた話（obs-websocket を利用）｜豊田 陽介｜note
　https://note.com/youtoy/n/nf404040a91c0
●OBS をスマホや M5GO（M5Stack）から遠隔制御 〜 MQTT や obs-websocket を利用 〜 - Qiita
　https://qiita.com/youtoy/items/23fb0e16f1a4428b5c9b

OBS の外部からの操作は、OBS に[プラグイン](https://github.com/Palakis/obs-websocket)を導入して動作させ、外部から特定の形式の JSON（※ 上記の note の記事で触れている内容）を WebSocket で送ることで実現できます。Node.js のプログラムと OBS との間で WebSocket による通信を行う部分では、[ws](https://www.npmjs.com/package/ws) を使いました。

今回用いたソースコードは以下となります。

```JavaScript
const { App } = require("@slack/bolt");
const WebSocket = require("ws");

const app = new App({
  socketMode: true,
  token: "【Botのトークン（SLACK_BOT_TOKEN）】",
  appToken: "【アプリのトークン（SLACK_APP_TOKEN）】",
});

const ws = new WebSocket("ws://localhost:4444");

app.message("休憩", async ({ message, say }) => {
  ws.send(
    JSON.stringify({
      "request-type": "SetCurrentScene",
      "message-id": "【任意の ID】",
      "scene-name":
        "【OBS上で設定したシーンの名前（この事例では休憩と表示するシーンの名前）】",
    })
  );
  console.log("休憩中の表示へ切り替え");
  await say("休憩の表示に切り替えたよ");
});

app.message("カメラ", async ({ message, say }) => {
  ws.send(
    JSON.stringify({
      "request-type": "SetCurrentScene",
      "message-id": "【任意の ID】",
      "scene-name":
        "【OBS上で設定したシーンの名前（この事例ではカメラ映像を表示する構成のシーンの名前）】",
    })
  );
  console.log("カメラ映像に切り替え");
  await say("カメラ映像へ切り替えたよ");
});

(async () => {
  await app.start();
  console.log("⚡️ Bolt app started");
  ws.on("open", function open() {
    console.log("Connection open");
  });
})();

```

そして、Slack からの OBS のシーン切り替えを試してみた時の様子は、以下となります。
Slack でテキスト入力を行うと（画面左）、OBS のシーンが切り替わりつつ（画面右）、Bot が応答を返してくれる（画面左）という動作が行われるのを確認できました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/seratch_ja?ref_src=twsrc%5Etfw">@seratch_ja</a> さんが書かれた Slack のソケットモードに関する記事の内容を試した続き。<br><br>処理を追加して、OBS のシーン切り替えを Slack上から行えるようなものを作ってみた。<br>とりあえず、「休憩」・「カメラ」というキーワードを Slack に書くと、OBSのシーン切り替えが行われる形。<a href="https://twitter.com/hashtag/SlackDevJP?src=hash&amp;ref_src=twsrc%5Etfw">#SlackDevJP</a> <a href="https://t.co/NIymHzIq5n">pic.twitter.com/NIymHzIq5n</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1349722623664558080?ref_src=twsrc%5Etfw">January 14, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## まとめ
今回、初めて Slack Bot開発・Bolt の利用を行い、その中で Slack ソケットモードを試しました。
さらに、以前作っていた仕組みを流用して Slack と OBS の連携も試してみました。

今回の内容で、Bolt を使った Bot開発まわりの部分は手を加えられてない部分なので、そちらも仕様をいろいろ調べたりしつつ、拡張できそうな方向を探ってみられればと思います。