LambdaとPythonでAPI GatewayをエンドポイントにしてSlackに何かを送る

# 経緯

2020/02/13に[JAWS-UG 初心者支部#23 次回のハンズオン勉強会向けのチューター向け予習会](https://jawsug-bgnr.connpass.com/event/163557/)へ参加することになりました。

Lambdaは、花屋時代にローカル環境でテスト実行してみてQiitaに上げたきりだったので
※その時の記事 => [Pythonでaws-sam-cliをローカル実行するまで](https://qiita.com/suwa3/items/505d137d7073c7a5243f)

もうすこし踏み込んでみたかったのと
(実用性を意識しながらLambdaを触ってみたいなぁ)
と、思った＆予習も兼ねて
**API GatewayをエンドポイントにしてLambdaを起動しSlackに何かを流す**
というのをやってみました。

API Gatewayをエンドポイントにした実行を試したいと考えた理由として
外部から連携したい場合、HTTPリクエストを受けて発火させる場面が多くあるので
これから効率化を考える際に、よく使いそうな手法として要領を掴んで慣れておきたかったからです。

逆にAPI Gatewayを使わないパターンとして
AWS内のサービスを使うときは、わざわざエンドポイントを外に置かなくても
AWSのサービス同士はだいたいIAMロールを使えばAWS内でセキュアに連携できます。

# 流れ

流れとしては
SlackでIncoming Webhookの設定をしてWebhook URLを控えます。

Lambdaのコンソール上で関数を作成して
Webhook URLをその関数内で使用し、連携させます。

API Gatewayのコンソール上でLambda関数を紐付けて
エンドポイントをデプロイすると、発火用のURLが発行されます。

そのURLにアクセスする(HTTPリクエストが届く)と
それを合図にしてLambdaが起動して
SlackのBotが起動する、という仕組みです。

# Slack側の設定
## Incoming Webhookの設定

まずはSlackの設定です。
『Slackをカスタマイズ』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/eb631242-075e-e50f-c0c3-f161fc42ee57.png)

左上の『MENU』から
『App 管理』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/c3e63a41-5141-2812-4474-6415b2b0ce01.png)

『 Incoming Webhook』を検索し、アプリを『Slackに追加』します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/0a20e0aa-fb93-e896-bf03-7a15055c7cba.png)

## Webhook URLを控える

Botを動かしたいチャンネルを選択したら、『Incoming Webhookインテグレーションの追加』をします。
発行されたWebhook URLを控えます。
セットアップの手順も、ザックリと参考にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/bdfd762c-0971-14c2-97d8-c705b800b75d.png)

ここでBotのアイコンや名前の設定なども行えます。

# Lambdaのセットアップ

## 関数の作成

関数名を入力します。
myfunctionでもtestでも、わかりやすい名前でOKです。
関数を記述する言語(ランタイム)はPythonを使用します。
実行ロールの選択は、今回特にAWS内のリソースには触らないので『基本的な Lambda アクセス権限で新しいロールを作成』でOKです。
RDSやAWS内の何かと連携する場合は、必要な権限を付与してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/93ce2943-becd-b2ae-83f3-1c73f5a250c6.png)

## 関数内にWebhook URLを仕込む

Slackに表示させるプログラムを作成します。

```
import json
import urllib.request

def lambda_handler(event, context):
    # TODO implement
    post_slack()
    return {
        'statusCode': 200,
        'body': json.dumps('pong')
    }

def post_slack():
    message = """
    本日のランチを提案するクマー
    1. 学食
    2. スパニッシュ
    3. 喫茶店
    """

    send_data = {
        "text": message,
    }
    send_text = "payload=" + json.dumps(send_data)
    # URLには自分のWebhook URLを入力してください
    request = urllib.request.Request(
        "https://hooks.slack.com/services/********************", 
        data=send_text.encode('utf-8'), 
        method="POST"
    )
    with urllib.request.urlopen(request) as response:
        response_body = response.read().decode('utf-8')
```

# API GatewayでAPI作成

## Lambda関数の紐付け

API Gatewayのコンソール画面から
『APIを作成』を選択して、PrivateではないREST APIの『構築』を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/7073cb67-987b-106b-47e3-1d97d5626cc3.png)

プロトコルの選択、諸々の設定を行います。

☑REST
☑新しいAPI
API名: My API
エンドポイントタイプ: リージョン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/85b7b97b-eda5-d742-2614-f1cfd59c8753.png)

『アクション』を選択して、リソースを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/bca6a02c-8381-558d-c2f2-b81e834fd283.png)

リソース名を設定します。
今回はSlackとしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/4da07b0a-a557-2fa3-e858-367b0b721a37.png)

次にメソッドを作成します。
『アクション』から、『メソッドの作成』を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/f9a7bf8e-a390-fce9-0ff9-f95bd56bb905.png)

Slackリソースのプルダウンをクリックして

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/a0729a26-247f-6f24-9ab3-45e532dfc011.png)

『GET』を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/5f15d40b-9a08-e93c-0a1f-0c13a0b26af8.png)

チェックをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/89f6934d-912c-fb8a-6502-3b307f19e23d.png)

セットアップをします。

☑Lambda関数
☑Lambdaプロキシ統合の使用
Lambda関数: myfunction
クリックすると候補が表示されるので、使用したいLambda関数を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/10a584ef-7daa-d2f9-1654-f4f0952ccd6e.png)

API Gatewayに、Lambda関数を呼び出す権限を与えます。

作成したAPIをデプロイします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/53002f19-1a38-0899-2963-cc9c34dea9d7.png)

デプロイのステージ名を決めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/d27e9c11-b387-7dbf-af95-b75ee0bc104d.png)

URLが作成されるので、こちらにアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/de285c19-e351-d0c2-bc7d-12c9218b7109.png)

早速Slackの通知が来ました。
と、いうことは..

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/549cb364-a20a-5e16-9fa3-33399ccc36de.png)

Slackを確認したところ
無事、届いていました👏

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449552/26440f50-87aa-b0e8-9058-c448ca4604a1.png)