【Python3+Lambda】Slackで2020年のご挨拶

#今回の背景
業務やコミュニティなどでslackを使用しており、日常的なやり取りも含めてslack上で行われることが多いです。そんな中、2019年大晦日にslackで新年のご挨拶をしよう！と思い立ったのが本記事の始まりです。
#slackで新年の挨拶をするために
###概要
slackの[Incoming Webhook](https://api.slack.com/messaging/webhooks)にメッセージをPOSTするLambda Functionを作成し、日本時間の2020/1/1 00:00:00に起動させます。
###処理フロー
かなりシンプルなフローですが、下図の通りです。
![名称未設定.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480978/83634662-9a1b-8115-e4b1-9aad02abf66a.jpeg)
<b>1.</b>2020/1/1 0:00にCloudWatch EventからLambdaをキックする。
<b>2.</b>1でキックされたLambdaがIncoming WebhookにメッセージをPOSTする。

それでは、実装に入ります！
##Incoming Webhookの準備
slackのApp追加ページよりIncoming Webhookを検索し、メッセージを送信するチャンネルを選択し、「Slackに追加」を押します。ボタンを押すと、Webhookのエンドポイントが生成されます。※このURLは誰でもメッセージをPOSTできてしまうので、第三者に漏洩しないようご注意ください。本記事でもURLはマスクの上、投稿します。
上記の詳細はこちらの記事（[SlackのIncoming Webhooksを使い倒す](https://qiita.com/ik-fib/items/b4a502d173a22b3947a0)）が参考になりましたので、記載させていただきます。

Incoming WebhookにPOSTするメッセージやその説明も併せて記載します。
まずは、メッセージの全容は下記の通り。

```python
    message = "<!channel> *Happy new year 2020!*"

    send_data = {
        "username": "〇〇_BOT",
        "icon_emoji": ":laughing:",
        "text": message
    }
```
個々の説明をすると

- <!channel>　メッセージの中に「@channel」を追加します。
- ＊XXX＊　　*で囲んだ文字をslack上で太字で表示します。
- username 　slackで表示する名前。
- icon_emoji 　iconとして表示する絵文字。
- text 　　　　メッセージ本文。

絵文字の種類はこちらの記事（[Qiita/Github/Slack/Discord 絵文字一覧](https://qiita.com/yamadashy/items/ae673f2bae8f1525b6af)）を参考にしました。

##Lambdaの実装
今回はPython3.8で実装しました。実装コードは以下の通り。

```python
import json
import urllib.request
import os

def lambda_handler(event, context):
    result = post_slack()
    #determine the existence of OK
    if 'ok' in json.dumps(result):
        body = json.dumps(result)
    else:
        body = 'NG!Watch logs of execution!'
        
    return {
        'statusCode': 200,
        'body': "slack result is " + body
    }

#method posting messages to slack    
def post_slack():
    message = "<!channel> *Happy new year 2020!*"

    send_data = {
        "username": "〇〇_BOT",
        "icon_emoji": ":laughing:",
        "text": message
    }
    
    send_text = "payload=" + json.dumps(send_data) #make a request data
    headers = {"Content-Type" : "application/json"}
    request = urllib.request.Request(
        os.environ["slack_url"], #url is configured as an OS environmental variable 
        data=send_text.encode('utf-8'),
        method="POST"
    )
    try:
        with urllib.request.urlopen(request) as response:
            response_body = response.read().decode('utf-8')
    except urllib.error.HTTPError as error:
        print(str(error.code) + error.reason)
    else:
        return response_body
```
大体のポイントとして、

-  payloadパラメターとして JSON ストリングを生成し、POSTする
-  lambdaの環境変数にslack endpointを設定し、処理実行時に取得する
-  slack responseに「OK」が含まれているかを判定し、メッセージ送信の成功を判定する
<br>※エラーハンドリングの作り込みは本実装では省略しています。

## 2020年を迎えた瞬間、処理を実行する
CloudWatch eventをLambdaの起動トリガーに設定します。CloudWatch側ではcron式で日時指定を行い、2020/1/1 00:00にLambdaをキックするようにします。このとき、CloudWatchは<b>UTCで動作しているため、</b>JST→UTCの変換のために、9時間遡って設定します。
そのため、cron式は下記の通りになります。

```
cron(0 15 31 12 ? 2019)
```
cronは（min hour day month sun-sat※ year）で指定します。
※曜日は今回不要なので、ワイルドカードを入れます。
Lambdaの起動トリガーに設定すると、下図のようになります。
<img width="1282" alt="スクリーンショット 2020-01-02 14.59.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480978/f59ac591-75ca-30b2-3024-1805cd2b84a9.png">
これであとは年越しを迎えるのみです！！
#新年を迎えました！
<img width="499" alt="スクリーンショット 2020-01-02 11.34.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480978/e43b54fb-440f-a1c5-f1ec-4187bf8ec08f.png">
無事作成したBOTから新年のご挨拶が来ました！新年にピッタリな記事が書けました。
サーバーレスアーキテクチャとSaaSのインテグレーションの利便性を改めて感じた次第です。大晦日の夜に新年のご挨拶BOTが作れるのですから。