はじめに
こんにちは!新卒3年目の加藤です。普段は社内システムの運用・開発を担当しています。
一番好きな社内ツールはSlackです。
Slackには単純にメッセージを投稿するだけではなく、APIを利用してアプリを作ることが可能です。
その中でも、何かのトリガーを元に処理を行うSlack Events APIというものがあります。
今回は試しに、そのSlack Events APIを利用し、「Timesチャンネルが開設されたときに通知をしてくれるアプリ」の作り方をご紹介します。
SlackのTimesチャンネルとは??
いわゆる「分報」と呼ばれるものです。
(別名「社内Twitter」とも)
今何をしているか、何に困っているかといった業務のことから、ちょっとした雑談など、個人個人が開設し、自由に利用することができるチャンネルです。
他の人のTimesチャンネルに参加しておけば、業務の合間の雑談やその人が何の業務をしているのかがわかるので、コミュニケーションの活性化に繋がります。
ニフティでもこのTimesチャンネルが活発に活用されていて、自身も、開発で詰まってしまった部分を呟いた際に、部署の垣根を超えて他のエンジニアの方が教えてくれた経験もよくあります。
また、配属1年目の新人の方には先輩のトレーナーがついてOJTを行いますが、リモートワーク全盛の昨今、常に隣に座って相談に乗るということが出来ません。
また新人の方も先輩の顔が見えないなか遠慮してしまい、積極的に先輩社員に質問するというのも難しかったりします。
そこで、Slackを使って今の自分自身の進捗や困ったことをどんどん自身のTimesに載せて、トレーナーがアドバイスをしてくれるような新しい働き方など、様々な使われ方がされています。
(中には、トレーナーを呼び出すボタンをTimesチャンネルに設置している新人もいるとか…?)
今回は、このTimesチャンネルを誰かが開設した際に、いち早く参加するために、その開設のお知らせをチャンネルにするアプリを作ってみます。
事前に準備するもの
次のものは事前に準備されていることを想定しています。
- Python(手元ではver 3.8で実行)
- Node.js(手元ではver 16で実行)
- AWSアカウント
- AWS CLIのインストールとプロファイルの設定
なお、手元ではMacを利用しています。
サービスの構成
今回はSlack APIから来たデータをAmazon API Gatewayを介してAWS Lambdaで処理するという、とてもシンプルな構成で作りたいと思います。
なお、AWSのサービスをGUIで設定するのは大変なので、今回はServerless Frameworkを用いてInfrastructure as Code(IaC)も組んでみたいと思います。
手順
では早速アプリを作っていきましょう!
作業はすべて適当なディレクトリにて行います。
最終的には、次のようなファイル・ディレクトリ構成になります。
1 2 3 4 5 6 7 8 9 |
. ├── .serverless ← 自動生成 ├── Pipfile ← 自動生成 ├── Pipfile.lock ← 自動生成 ├── lambda_function.py ← 手順4内にて作成 ├── node_modules ← 自動生成 ├── package-lock.json ← 自動生成 ├── package.json ← 自動生成 └── serverless.yml ← 手順3内にて作成 |
1. Slackアプリの設定
まずはSlack APIを利用するためにSlackアプリの設定をします。
https://api.slack.com/ の「Create an app」からSlack アプリを作成しましょう。
その際、以下のような画面が出ると思います。
これは、Slackアプリをどうやって設定するか選択する画面です。
From scratch
で画面からポチポチ設定していってもいいですが、少し大変なので、今回は manifest
を使ってみましょう。
ワークスペースを選んで、YAMLには下記をコピペします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
display_information: # アプリの設定 name: NofityNewTimes description: Notify new times channels features: app_home: home_tab_enabled: true messages_tab_enabled: false messages_tab_read_only_enabled: true bot_user: # Botの設定 display_name: Notify New Times always_online: true oauth_config: # 許可するscopeの設定 scopes: bot: - channels:read # channel_createdのイベントを受け取るのに必要 - chat:write # Slackにメッセージを投稿するのに必要 - chat:write.public # チャンネルにアプリを追加しなくても投稿できるようにする settings: event_subscriptions: # イベントを受信する設定 request_url: https://example.com # イベント送信先。後で変えるので一旦適当 bot_events: # 受信するイベント。今回はチャンネルが作られたら発火します。 - channel_created org_deploy_enabled: false socket_mode_enabled: false token_rotation_enabled: false |
これで「Create」をし、アプリができたら「Install to Workspace」をクリックしてワークスペースにインストールしておきましょう。
2. 環境構築系
実際のアプリを作っていく前にアプリを構築するための環境を整備しましょう。
まずは、デプロイに利用するServerless Frameworkと、デプロイパッケージにPythonの依存パッケージを自動で含めてくれる便利なプラグインをインストールします。
1 2 3 4 |
% npm init (npm initの設定はすべて何も入力せずEnterでOK) % npm i -g serverless # Serverless Frameworkインストール % npm i --save serverless-python-requirements # デプロイパッケージに自動でPythonパッケージを含めてくれるプラグイン |
次にPython関連の準備です。
今回は、仮想環境として pipenv
を使うので、そのインストールと仮想環境の作成をします。
1 2 |
% pip install pipenv==2022.8.5 # pipenvインストール % pipenv --python=3.8 # pipenv仮想環境作成 |
最後に、作成した仮想環境に対して、今回の開発に必要なPythonパッケージをインストールしましょう。
1 |
% pipenv install slack-bolt # Slack Boltインストール |
3. Serverless Frameworkの整備
AWSのリソースを自動で作成してくれるServerless Frameworkの設定ファイルを作ります。
serverless.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
service: notify-new-times frameworkVersion: '3' custom: pythonRequirements: # Pythonの依存パッケージを自動でデプロイに含めてくれるプラグインの設定 usePipenv: true # pipenvを使うためtrue provider: name: aws # AWSにデプロイ runtime: python3.8 # LambdaのランタイムにPython3.8を利用する region: ap-northeast-1 # デフォルトのAWSリージョン(東京) iam: # デプロイするLambda関数に与えるロールの設定 role: statements: - Effect: "Allow" Action: # Slack Boltでは下記が必要 - "lambda:InvokeFunction" - "lambda:GetFunction" Resource: "*" environment: # Lambda関数に設定する環境変数 SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN} # SlackアプリのAPIトークン SLACK_SIGNING_SECRET: ${env:SLACK_SIGNING_SECRET} # Slackアプリのシークレット(リクエストが正当なものか検証するのに必要) CHANNEL_ID: ${env:CHANNEL_ID} # 通知をするSlackチャンネルのチャンネルID package: # デプロイパッケージに含めるファイル patterns: # lambda_function.pyのみ必要なので、全部を除いたあとにlambda_function.pyのみ追加 - '!**' - 'lambda_function.py' functions: # Lambda関数の設定 notify-new-times: handler: lambda_function.lambda_handler # 最初に実行されるファイルと関数名 timeout: 10 # Lambda関数のタイムアウト(10秒) events: # Lambda関数のトリガー - httpApi: # API Gateway(自動でデプロイ時にAPI Gatewayも作成してくれる) method: POST path: /notify-new-times plugins: # 利用するプラグイン - serverless-python-requirements |
4. Lambda関数の準備
では、実際にLambdaで動かすスクリプトを作ります。
lambda_function.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler import os # Slack Boltのappの初期化 app = App(token=os.environ.get("SLACK_BOT_TOKEN"), signing_secret=os.environ.get("SLACK_SIGNING_SECRET"), process_before_response=True) # LambdaのようなFaaSでSlack Boltを利用するときはTrue # Slack APIにackを返す関数 def respond_ack(ack): ack() # 指定されたチャンネルにTimesチャンネルの開設者とそのリンクを送信する関数 def notify_created_times(body, client): channel_info = body["event"]["channel"] if channel_info["name"].startswith('time'): # チャンネル名が「time」で始まっていれば notify_text = f'<@{channel_info["creator"]}>さんが<#{channel_info["id"]}>を開設しました:partying_face:' client.chat_postMessage(channel=os.environ.get( 'CHANNEL_ID'), text=notify_text) # channel_createdのイベントが来た時に実行される関数 # Ref:https://api.slack.com/events/channel_created app.event('channel_created')( ack=respond_ack, # Slack APIに3秒以内にackを返さないといけないので、それを行う関数 lazy=[notify_created_times] # 時間がかかりそうな関数はすべてこっちに載せる ) # 最初に実行される関数 def lambda_handler(event, context): slack_handler = SlackRequestHandler(app=app) return slack_handler.handle(event, context) |
5. 環境変数の設定
デプロイに必要な環境変数を設定します。
APIトークンは「OAuth & Permissions」に、Signing Secretは「Basic Information」にそれぞれ書かれています。
1 2 3 |
% export SLACK_BOT_TOKEN=xoxb-xxxxxxxxx # SlackアプリのAPIトークン % export SLACK_SIGNING_SECRET=xxxxxxxxxxxx # SlackアプリのSigning Secret % export CHANNEL_ID=xxxxxxx # 通知先のSlackチャンネルID |
6. デプロイ
ではデプロイしましょう!
1 |
% sls deploy --aws-profile プロファイル名 # Serverless Frameworkでデプロイする |
7. イベント通知先のURLを設定する
デプロイに成功すると、ターミナルの最後の方にendpoint URLが記載されているはずです。
これが、今回のデプロイで作成されたAPI GatewayのURLになるので、これをSlack APIに設定しましょう。
これで、チャンネルが作成された場合に、Lambdaが起動するようになります。
動作確認
Timesチャンネルを作成してみると…
無事に通知されました!
最後に
ニフティではTimesチャンネルを多く活用しており、コミュニケーションの活性化に繋げています。
近年ではリモートワークによりコミュニケーションが希薄になりがちですが、そんな中でもSlackを通じてコミュニケーションを維持し、困ったことや雑談に対して誰かがすぐに反応をくれる文化は、ニフティの良い文化かなと個人的に思っています。
今回は、そんなTimesチャンネルのメリットを最大限に活かすために、Slack Events APIを用いて、Timesチャンネルの開設を通知してくれるアプリを作ってみました。
もし、Slackを活用していらっしゃれば、ぜひ参考にしてみてください。
また、今回はAPIのイベントトリガーとして「チャンネルが作られたら」というトリガーのみ利用しましたが、それ以外にもたくさんのトリガーで処理をさせることができるので、ぜひ試してみてください!