ソラコムの【あのボタン】で勤怠打刻してみた（その1）

みなさん、在宅勤務やってますか？そして在宅勤務の打刻忘れてませんか？僕は忘れっぽいんですが、在宅勤務の打刻だけは忘れてません。が、打刻をしたあとslackのスレッドにも業務を開始する旨を開始時間と一緒に投稿する必要があります。そして退勤するときも同様に打刻した後に同じスレッドに退勤時間を投稿する必要があります。**これがまあ面倒くさいんですよ。**面倒くさいことはなんとかして解決する、それがエンジニアってもんじゃないですか（偏見）

というわけで、今回はこのSlackへの投稿を自動化してみたいと思います。
※今回はプライベートのテスト環境でためしてます。

## 今回使うもの
さて何をつかってこれを自動化しようか考えたときに机の上にあるものを見つけました。
![IMG_20200511_215729.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/2360a460-b31c-276c-1c93-acb1ac2c0ef4.jpeg)
そうです、以前Soracom UGのハンズオンで買った**あのボタン**です。ハンズオンが終わった後には、[ラズパイと連携するネタ](https://qiita.com/K_M95/items/d07fe02d893b9243a7ab)に使いその流れで夏場はこれを使って遠隔でエアコンの電源をつけるリモコンとして使っていました。そして今年も稼働させようとしてたところでした（いや、本当ですよ）。ですが、今はそのシステムよりも打刻をこれで楽にさせるほうが大事だと思ったので、これを使っていきたいと思います。

## イメージ
3種類のトリガーを生かしてこう割り振りたいと思います

- シングルクリックで出勤の連絡をする
- ダブルタップで退勤の連絡をする
- ロングタップは直前の投稿を消す（できたら実装したい）

## Slackのtokenを取得
まずはslackにメッセージを投稿させるためにtokenを取得します。[こちら](https://api.slack.com/apps)のサイトから、```Create an App```をクリックして、新規のSlack appを作成します。
![コメント 2020-05-11 224520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/4e40239e-f8dc-7c47-4d7d-3fef164be92a.png)

このようなダイアログが表示されるので、ここでApp Nameと今回使用するワークスペースを指定して、下の```Create App```をクリックします。App Nameはわかりやすい名前にしておきましょう。後で変更することもできます。
![コメント 2020-05-11 224630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/e6499cd5-ba61-e0c1-c0f0-983caf8a41a3.png)

作成すると、以下の画面が出力されるので、右下の```Permissions```を選択しておきます。
![コメント 2020-05-11 225736.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/d73a2f29-04f7-bb55-2fbc-d33429aab367.png)

次の画面をスクロールしたときに```Scopes```という項目がありますが、こちらはUser Token Scopesの中から```chat:write```、そして```channel:history```を選択します。
![コメント 2020-05-11 234143.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/43333c0c-6869-45e3-f5e5-e31e2775bfdc.png)


上にスクロールして、```Install App to Workspace```をクリックします。
![コメント 2020-05-11 233735.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/4eab4c1d-e28f-c717-d9e2-f23948e19bc6.png)

以下の画面が出るので、```Allow```を押して次に進みます。
![コメント 2020-05-11 234241.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/10b3f4f3-0123-347d-1a85-3c5ce851cac9.png)

その後、以下のようにOAuth Access Tokenが発行されるので、コピーしておきましょう。
![コメント 2020-05-11 234734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/4358bfdd-d337-4ae5-090d-d23384811ea4.png)



## lambdaの実装
### その前に今回のシチュエーション
今回はslackに勤怠チャンネルがあって、下図のようなメッセージが毎朝投稿されるからこれに出勤時刻、退勤時刻を投稿するというシチュエーションを考えます。（念のために言いますが、あくまで架空のものです）
![コメント 2020-05-12 012340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/a9c37d8d-b5bc-c046-778f-3798b483d833.png)

### 今回の実行環境

- AWS lambda(RuntimeはPython3.6)
- SlackのPython SDK

### 環境構築(lambdaを作成)

1. AWSにログインして検索窓から```lambda```と入力しlambdaにアクセス
2. 関数名はお好みに設定し、ランタイムはPython3系（今回はPython3.6）を選択
3. あとは特にいじらずに```関数の作成```をクリック
4. SlackのSDKを使うので、Cloud9で開発環境を構築する（特に何も設定をいじらずに順に設定してOK）
5. Web IDEを立ち上げて右側のlambdaマークをクリックして、先程作成したlambdaを選択し、IDE環境にインポートする
![コメント 2020-05-12 025319.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/a7a61a0c-04cc-995c-b990-313832e46c44.png)
6. IDEの下のターミナルで```cd YOUR_LAMBDA```と入力し、実行環境にディレクトリを移動したら、以下のコマンドを実行し、SlackのSDKをインストールする
 
```bash
python -m pip install --target=./ slackclient
```


### ソースコード
デフォルトの関数を消して、以下のソースコードに書き換えます。channel IDには皆さんのお使いのワークスペースのアドレスの```https://WORKSPACE_URL/archives/channelId```の形式のとき、```channelId```の文字列をコピペします。

```python
from slack import WebClient
from slack.errors import SlackApiError
from datetime import datetime
import datetime as dt
import json
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

token = "YOUR_TOKEN"
client = WebClient(token=token)

def lambda_handler(event, context):
    logger.info('request event: \n' + json.dumps(event))
    
    # クリックイベントを取得する
    click_type = event['deviceEvent']['buttonClicked'].get('clickType')
    logger.info("click_type: " + click_type)
    
    try:
        # 返信するスレッドのtsを取得
        channelId = 'YOUR_CHANNEL_ID'   # https://WORKSPACE_URL/archives/channelId
        response = client.conversations_history(channel=channelId)
        ts = response["messages"][0]["ts"]
        
        # 投稿時刻を設定し、スレッドに送信
        nowDate = datetime.utcnow() + dt.timedelta(hours=9)
        nowTime = nowDate.strftime("%H:%M")
        if click_type == "SINGLE":
            message = "業務開始します {}".format(nowTime)
        elif click_type == "DOUBLE":
            message = "業務終了します {}".format(nowTime)
        response = client.chat_postMessage(
            channel=channelId,
            thread_ts=ts,
            text=message)
        logger.info(response)
        return{
            'statusCode': 200,
            'body': 'Succeed'
        }
    except SlackApiError as e:
        logger.info(e.response["ok"] is False)
        logger.info(e.response["error"])

        return {
            'statusCode': 500,
            'body': f"Got an error {e.response['error']}"
        }

```

### テスト
Cloud9上でlambdaを開発したときには、その場で関数をテストすることができます。右側のlambdaのタブの上部にある再生ボタンの隣の下矢印をクリックして、```Run Local```を選択して再生ボタンを押します。
![コメント 2020-05-12 035409.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/dfb77140-e43c-f3df-c827-ff70db31c3e3.png)

これでローカル環境で実行できる状態ですが、実際にLTE-Mボタンを押したときにlambdaが受け取るデータが無いとテストができません。そこで以下のjsonをコピーして、```test payload```に貼り付けます。なお、使うJSONは[以前](https://qiita.com/K_M95/items/d07fe02d893b9243a7ab#lambda)使用したものと全く一緒ですが、今回のコードの動作に影響はないのでそのまま使います。

```json
{
    "deviceInfo": {
        "deviceId": "G030PMXXXXXXXXXX",
        "type": "button",
        "remainingLife": 94.2,
        "attributes": {
            "projectRegion": "us-west-2",
            "projectName": "One-click-Raspi",
            "placementName": "button1",
            "deviceTemplateName": "RequestCmd"
        }
    },
    "deviceEvent": {
        "buttonClicked": {
            "clickType": "SINGLE",
            "reportedTime": "2019-01-24T18:49:36.813Z"
        }
    },
    "placementInfo": {
        "projectName": "One-click-Raspi",
        "placementName": "button1",
        "attributes": {
            "SINGLE": "{\"cmd\":\"green\"}",
            "DOUBLE": "{\"cmd\":\"blue\"}",
            "LONG": "{\"cmd\":\"red\"}"
        },
        "devices": {
            "RequestCmd": "G030PMXXXXXXXXXX"
        }
    }
}
```

貼り付けたら左上にあるRunボタンをクリックして、テストしてみます。以下のように指定したチャンネルに最後に投稿されたスレッドにメッセージが送信されれば、成功です。
![コメント 2020-05-12 130512.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/35faa054-4f9d-2067-d820-f0fa118b50d6.png)


## デプロイ
それでは、最後に作成した関数をlambdaのリソースにデプロイします。IDEの右側にあるlambdaタブで先程作成したlocal lambdaを右クリックして```deploy```を選択して関数をデプロイをします。デプロイを終えて、lambdaのリソースに移動し先程作成したlambdaにCloud9からデプロイした環境が反映されていたら成功です。
![コメント 2020-05-12 041828.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170520/f69158d7-d4a9-d96f-2cac-4aecfee0a3b3.png)

##今回はここまで
長くなったので、今回はここまでにします。次回いよいよボタンからこのlambdaを実行していきます。

後編はこちら
[ソラコムの【あのボタン】で勤怠打刻してみた（その2）](https://qiita.com/K_M95/items/aa022f7d39a5045a3098)