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


今回の背景

業務やコミュニティなどでslackを使用しており、日常的なやり取りも含めてslack上で行われることが多いです。そんな中、2019年大晦日にslackで新年のご挨拶をしよう!と思い立ったのが本記事の始まりです。

slackで新年の挨拶をするために

概要

slackのIncoming WebhookにメッセージをPOSTするLambda Functionを作成し、日本時間の2020/1/1 00:00:00に起動させます。

処理フロー

かなりシンプルなフローですが、下図の通りです。

1.2020/1/1 0:00にCloudWatch EventからLambdaをキックする。
2.1でキックされたLambdaがIncoming WebhookにメッセージをPOSTする。

それでは、実装に入ります!

Incoming Webhookの準備

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

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

    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 絵文字一覧)を参考にしました。

Lambdaの実装

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

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」が含まれているかを判定し、メッセージ送信の成功を判定する
    ※エラーハンドリングの作り込みは本実装では省略しています。

2020年を迎えた瞬間、処理を実行する

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

cron(0 15 31 12 ? 2019)

cronは(min hour day month sun-sat※ year)で指定します。
※曜日は今回不要なので、ワイルドカードを入れます。
Lambdaの起動トリガーに設定すると、下図のようになります。

これであとは年越しを迎えるのみです!!

新年を迎えました!


無事作成したBOTから新年のご挨拶が来ました!新年にピッタリな記事が書けました。
サーバーレスアーキテクチャとSaaSのインテグレーションの利便性を改めて感じた次第です。大晦日の夜に新年のご挨拶BOTが作れるのですから。