Slack WorfFlowとChatbotを使って日報報告ツールを作る

この記事は[AWS LambdaとServerless Advent Calendar 2020](https://qiita.com/advent-calendar/2020/lambda) の14日目の記事です。

# 背景

Slackで日報を入力する際に毎回フォーマットをコピペするのは割と面倒なのでそれを自動化したかったのと、入力されたデータをConfluenceなどに自動でまとめて出力できたら楽だと思ったのでDynamoDBに日報データを保存する処理を作りました。


# 完成図
![スクリーンショット 2020-12-13 20.04.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/1dd5742a-53bc-0053-530d-3b3e9b41955b.png)

![スクリーンショット 2020-12-13 20.09.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/47ac2afc-d32d-a2a3-2bc6-4d161e9226a3.png)


# Slack WorkFlowをセットアップする

1. Slack WorkFlowの作成
2. 入力フォームを作成
3. 入力されたデータを整形してChatbotでLambdaを起動
4. LambdaでDynamoDBにデータを挿入

## Slack WorkFlowの作成

まずは[Slack WorkFlow](https://slack.com/intl/ja-jp/help/articles/360035692513-%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%95%E3%83%AD%E3%83%BC%E3%83%93%E3%83%AB%E3%83%80%E3%83%BC%E3%82%AC%E3%82%A4%E3%83%89)を作成します。

![スクリーンショット 2020-12-13 20.29.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/1dbdfd93-3cd5-2ae7-051b-ba7a23eee3d2.png)

作りたいワークフローの名前を入力し、今回はショートカットを選択します。

![スクリーンショット 2020-12-13 20.27.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/c3d7e003-ad8c-9b4d-f72f-8548e68f2539.png)

最後にワークフローをセットしたいチャンネルを指定すれば完了です。


## 入力フォームの作成

「ステップを追加」から「フォームを送信する」を選択し、入力フォームを作成します。
自由にフォーマットを作成しましょう。

![スクリーンショット 2020-12-13 20.40.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/4cdbd3a6-2238-e5ee-50b6-fe4e6e2425b0.png)


## 入力されたデータを整形してChatbotでLambdaを起動

最後に「メッセージを送信する」を選択し、送信するメッセージにChatbotで起動するコマンドを書きます。
この時、下の画像のように入力フォームで設定した値や入力したユーザーを指定することが可能です。

```
@aws lambda invoke --payload "{\"report_date\":\"可変テキスト\", \"user\":\"可変テキスト\", \"team\":\"可変テキスト\"}" --function-name dev-ava-daily-report --region ap-northeast-1
```

![スクリーンショット 2020-12-13 20.45.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/da5c7274-856e-8974-dbd1-0dfed5b6c56a.png)

注意点として「入力フォーム」で入力した改行は半角スペースに自動で変換されるのと、「メッセージを送信」のテキスト欄のダブルクォートが勝手に別の文字コードに変換される場合があります。
両方ともSlack WorkFlowの仕様なのですが、できたら直してくれないかなぁ…


# Chatbotの設定

ChatbotをSlackに紐付けます。
（Slackの管理者権限が必要な場合があります。）
![スクリーンショット 2020-12-13 22.11.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/de20e156-83cc-3489-4b83-57e2773142b1.png)

そうしたら次はチャンネルと紐付けます。
ポリシーテンプレートで「Lambda 呼び出しコマンドのアクセス許可」を追加します。
それ以外は紐付けたいSlackチャンネルの設定に合わせます。

また厳密に起動したいLambdaを絞る場合は作成されたIAMの権限を変更しましょう。

![スクリーンショット 2020-12-13 22.13.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/680e1d35-ab1b-5aac-f73c-a8758a5e2d11.png)


# Lambdaの作成

最後にデータをDynamoDBに保存するコードを書きます。
このあたりの設定の説明に関しては省きます。


```python

import json
import datetime
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table("DailyReports")

def lambda_handler(event, context):
    print("Received event: " + str(event))
    decord_event = json.loads(event)
        
    dt_now = datetime.datetime.now()
    report_datetime = "{}-{}".format(str(dt_now.year), event['report_date'])
    # 0なし（2020-8-1）から0埋め（2020-08-01）にフォーマット
    # DynamoDBの仕様でこうしないとフィルターできない
    report_date = datetime.datetime.strptime(report_datetime, "%Y-%m-%d")
    target_date = report_date.strftime("%Y-%m-%d")
    
    expiration_datetime = dt_now + datetime.timedelta(days=45)

    put_response = table.put_item(    
        Item = {
            "TargetDate": target_date,
            "UserName": event['user'],
            "Team": event['team'],
            "ExpirationTime": int(expiration_datetime.timestamp())
        }
    )
    
    if put_response['ResponseMetadata']['HTTPStatusCode'] != 200:
        print(put_response)
    else:
        print('PUT Successed.')
    
    return {
        'message': json.dumps('Save daily report successufly!')
    }
```


# 動作確認

Slackの文字入力欄の隣にある青いイナズママークを押すとそのチャンネルに登録されたWorkFlowが表示されます。

![スクリーンショット 2020-12-13 23.01.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/aef968f8-81d3-5b61-ee50-8e29fb25d404.png)

作成したワークフローを選択すると入力欄が表示されるので設定した項目を入力して確定すると、以下のように自動でChatbotが実行されます。
最後に「Would you like me to do so?」と尋ねられるのでYesを押したらLambdaが実行されます。

![スクリーンショット 2020-12-13 23.24.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391127/de4594c7-4139-f99c-1fae-d87b67b3df02.png)


# 実際に使ってみて感じたこと

ChatbotはLambdaを実行する際に必ず実行確認をされるのやコマンドの実行履歴が表示されるのが少々面倒に感じました。
後者に関しては入力用チャンネルと出力用チャンネルとを分けることで対策できますが、前者に関しては解決策が現状なくSlack WorkFlowの入力だけで完結できないのが悩みどころです。

またSlack WorkFlowに関しては割と切実に日時（カレンダー）の入力フォーマットの追加と、改行を半角スペースではなく`\n`などに置き換えるられるようにして欲しいです。
現状だと痒いところに手が届かないツール止まりになってしまうので、これができるだけで自由度が結構上がるようになると思います。
（半角スペースだと文字列のパースを考えたり実装したりするの大変なんですよね…）


# 最後に

Chatbotのおかげで少しだけLambdaなどの仕組みを理解しているだけで、ちょっとしたツール程度ならかなり簡単に実装することができるようになったと思います。

今回はデータを保存するところまでだけ触れましたが、自分の場合はこの後にCloudWatch Eventや外部APIなどを組み合わせて自動でデイリーの議事録を作るのに使ったりしています。

### 参考資料
[SlackワークフロービルダーでAWS Chatbotのコマンドをテンプレ化する](https://qiita.com/kanga/items/9b43ea182b1c2ce07990)
[AWS ChatbotからのLambda起動をCloudFormationとSlackワークフローで使いやすくする](https://dev.classmethod.jp/articles/chatbot-lambda-cfn/)