定時にビデオキャプチャして画像を投稿するSlack botの作成(2021.7.11, 2021.7.15追記)

Summary

scheduleモジュールなどを使ってApp内で時間をカウントしても良いけれど、それだと時間を監視するthreadが別に必要となったり、時刻指定用のIFを実装する必要があったりと面倒。
Slack上の特定のトリガーイベントを監視してキャプチャーを実行するlistner botとして実装し、Slackの/remind機能などでトリガーイベントを定期的に発生させることにした。
この方法なら、listner botは実行時刻などは気にせず、ただchannelを監視しておくだけで良いし、定点観測以外に個別にキャプチャを実行したい場合にも簡単に対応できる。
Slackのchannelで’shot’/‘Shot’(大文字小文字の区別なし)という文字列を投稿すると、MacのBuilt-inビデオカメラからの画像をキャプチャしてslackに画像ファイルをアップロードしてくれるSlack botを作成する。

【2021.7.15追記】concurrent.futuresでマルチプロセスを実現
SocketModeHandlerと、cv2.imshow()は同じメインスレッドに入れる必要があり、 cv2.imshow()やcv2.waitKey()のために専用のwhileループを組めないので、 キャプチャ中のカメラデバイスの画像をウィンドウに表示することができていなかった。 今回、concurrent.futuresのマルチプロセス機能で表示を実現した。

image captured and uploaded by CaptureBot

Slack APIのページにメインで書かれている方法は、AWSやAzureなどのHTTP postを受け付けられるpublic URL endpointと契約してメッセージを中継してもらえないと、Slackのメッセージをbotが受け取ることができない。
これに対して、Socket Modeで通信を行う場合には、サーバが不要というメリットがある。

Socket Modeに関する紹介記事(2021.1.13)はこちら

動作仕様

商用エンドポイントサービスの契約が不要なslackのSocket Modeを用いてSlack botを作成する。

Slackに特定の文字列を含む文をポストすると、そのポストをトリガーとしてbotがローカルのMacのカメラを用いて撮影した画像をポストし返してくれるアプリケーションをslack_bolt (Python)を用いて作成する。

定時にslackにメッセージイベントを送信するには/remindを使う

App内で定時実行の時間管理まですると、トリガーを監視するlistnerのthreadと、指定時刻に自主的に起動するtimer threadを実装した上に、トリガーを受けてコマンドを解釈し、時刻設定を行うインターフェースも実装する必要が生じる。これらは面倒なので、あるものはそのまま使う方針で、定時実行のトリガーは、Slack botがもともと持っている/remind機能を利用することとする。

/remindは、たとえば以下のように設定できる。

/remind me to ask @hellobot2000 to shot a photo every weekday at 7:05

使い方の解説はこちら

Appの新規作成と設定

https://api.slack.com/appsで 「Create New App」から新規のAppを作成できる。

手順は以下のとおり

  1. ボットを設置したいSlack Workspaceとそのchannelを作成する
  2. https://api.slack.com/にWorkspaceのアカウントでログイン
  3. https://api.slack.com/appsで「Create New App」
  4. tokenの生成(メモしておく)やmanifestoの設定(users.readも設定)をしておく
    (Socket Modeの許可とApp-level tokenの生成も忘れずに)
  5. Slack Workspaceを指定してAppをインストール
  6. tokenの再発行や設定の追加は「OAuth & Permissions」の「scopes」などから行う
  7. pythonからAppを起動

Appの作り方については以下の記事を参照