AWS lambdaを使ったslackとDocBase連携システム作成手順

## やったこと
DocBase APIとslack WebhookURLを利用してAWS lambdaで、1日前（月曜日だけは金、土、日曜日の3日間）にDocBaseの自分が所属する事業部宛に投稿された記事を取得して、slackに通知するシステムを作成しました。

## 背景
以下の記事に書かれている通り、DocBaseのオーナー管理者権限を持っていればDocBaseのWebhookURLを利用して簡単にslackと連携することができます。
今回、私は上記の権限がなかったため、DocBaseのメモ検索APIをlambdaで呼び出し、slackのwebhookURLを利用して通知するシステムを作成しました。
この先、同じようなシステムを作りたいという人が現れた際に、この記事が少しでもお役に立てれば幸いです。

https://help.docbase.io/posts/13676

# 手順

## ①slackのWebhookURL発行
1.slack API( https://api.slack.com/apps )にアクセスする
2.`Create an App`を押して、`From scratch`を選択する
![c9dbf888-e6cf-406d-9db0-4fe74d1d299a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/20ba1046-dea0-eee7-4762-97ff9f8a4abe.png)
![スクリーンショット 2022-11-28 182613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/084dc528-401f-69d0-001a-385fd5386c7f.png)
3.App Nameに任意の名前を付け、Pick a workspace to develop your app in:からワークスペースを選択して、`create App`を押す
![スクリーンショット 2022-12-05 171240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/639f1a74-aae2-70ea-962c-277cffbb626f.png)
4.作成したアプリの設定画面に遷移し、右下にある`Permissions`を選択する
![スクリーンショット 2022-12-05 171431.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/76bef4a9-a8ae-79bd-1130-4a57099d081e.png)
5.ページ中部にあるScopesの中の`Add an OAuth Scope`を押下し、出現したプルダウンから`chat:write`を選択する
![スクリーンショット 2022-12-05 171618.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/2c39d5f8-7853-0f42-78df-d4a1c91c5cfd.png)
![スクリーンショット 2022-12-05 171643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/876ae921-fb1a-6315-bc1a-91c143b621e9.png)
6.左サイドバーの`App Home`から、App Display Nameの`Edit`を選択する
![スクリーンショット 2022-12-05 171758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/db65f87d-b111-a9bc-13aa-9f6995fc4e21.png)
7.Display Name(Bot Name)にbotの表示名を、Default usernameにユーザー名を入れて`Add`を選択する
![スクリーンショット 2022-12-05 171838.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/39bafb47-6410-5d35-8797-8671757e1476.png)
8.slackに移動して通知botを導入したいチャンネルを右クリックし、`チャンネル詳細を表示する`を選択する
![スクリーンショット 2022-12-13 160459.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/9edb7eaf-b598-af17-aaac-19325bcf21a6.png)
9.`インテグレーション`を選び、Appカテゴリ内にある`アプリを追加する`を押下する
![スクリーンショット 2022-12-13 160559.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/04fb7315-24aa-de55-36f6-812e6d1c29dd.png)
10.検索窓で先ほど作ったbot名を入れ検索。下に表示されたbotの`追加`を押下する
※画像では既に追加済みのため、「表示する」ボタンになっている
![スクリーンショット 2022-12-13 161226.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/08b55ed6-5e5a-4c9d-6551-93bd5a3423f6.png)
11.チャンネルにbotが追加されたことを確認する
![スクリーンショット 2022-12-13 162019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/8df65791-f534-77ba-5ff1-d84bccb90ea7.png)
12.slackAPI設定画面に戻り、左サイドバーの`Incoming Webhook`を選択、Activate Incoming Webhooksを`On`にして`Add New Webhook to Workspace`を押下する
![スクリーンショット 2022-12-18 173126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/0334d2b8-18b3-3f84-7c1c-ca194ad7a819.png)
13.botの投稿先を聞かれるため、プルダウンから投稿したいチャンネルを選択して`許可する`ボタンを押下する
![スクリーンショット 2022-12-18 173435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/56707c98-3b0e-40c2-d15f-822f6636dbcb.png)
14.WebhookURLが発行されたことを確認する
![スクリーンショット 2022-12-18 173709.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/776af754-ef63-cadb-41a8-cf0179e0ecda.png)

ここで発行したWebhookURLはlambdaからメッセージを送信する際に使用します。





## ②DocBaseのアクセストークンを発行
1.DocBaseのアカウント設定のページを開き、サイドバーにある`アクセストークン`を選択する
![スクリーンショット 2022-12-06 190521.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/65d8f678-dc51-1815-982d-574846394e3e.png)
2.`トークンを作成`を選択する
![スクリーンショット 2022-12-06 190029.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/99742402-f167-3c95-25b0-12a9ecc1fb89.png)
3.任意の名前と有効期限を入力して`作成`ボタンを押す
※有効期限は特に必要なければ空欄でOK
![スクリーンショット 2022-12-06 190648.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/43690591-b9ed-e203-2066-b55c40e018f5.png)
4.表示されたアクセストークンをコピーする
![スクリーンショット 2022-12-06 190849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/6f7ea761-49f7-8186-7271-fd9bb62b7f2b.png)

ここで作成したアクセストークンはDocBaseAPIを利用する際に使用します。

## ③lambdaの設定
1.AWSコンソールにログインして、リソースの中から`lambda`を選択する
![スクリーンショット 2022-12-13 162946.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/e7469c48-a335-e029-9d65-62b49e687e3d.png)
2.画面右側にある関数の`作成`ボタンを押下する
![スクリーンショット 2022-12-18 131955.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/c45a45b8-f08c-2bbb-a476-2828c1305c9f.png)
3.関数の作成画面で「一から作成」を選択。任意の関数名を付け、ランタイム（使用する言語）とアーキテクチャを選択し、右下の関数を`作成`ボタンを押下する
※今回ランタイムはpython3.9、アーキテクチャはx86_64を選択している
![スクリーンショット 2022-12-18 132208.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/09fb7077-7d85-e518-2255-d9ffa43f93b2.png)
4.関数が正常に作成されたのを確認する
![スクリーンショット 2022-12-18 132747.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/34446646-cf57-7cad-b66a-ae885e097858.png)

## ④コードを記述する前の下準備
DocBaseのAPIを利用する際とslackへのメッセージ送信の際にrequestsモジュールを利用するため、コードの最初でimport requestsをします。
![スクリーンショット 2022-12-18 155355.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/b3721c7d-b2bf-291d-36b6-5c472cfa65b4.png)
しかし、初期のlambdaにはrequestsモジュールが存在しないため、実行すると以下のエラーが表示されます。
![スクリーンショット 2022-12-18 155414.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/487e3fd5-f6ca-d973-4d43-2742ece39372.png)

そこでライブラリを追加するために以下の手順を行う必要があります。
参考:https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-import-module-error-python/

1.pythonという名前でフォルダを作成する
※ここでフォルダ名がpythonでないと、lambdaのレイヤーに追加した際に読み取ってもらえないためエラーになります。
2.python環境を用意し、`pip install -t /python requests`コマンドで先ほど作成したpythonフォルダ内にライブラリをダウンロードする
3.ダウンロードが完了したら、pythonフォルダをzip化する
4.lambda画面に戻り、ハンバーガーメニューから`レイヤー`を選択。`レイヤーの作成`ボタンを押下する
![スクリーンショット 2022-12-18 164740.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/fbf06a76-2e97-11e1-45df-0e980b3fbc19.png)
5.任意のレイヤー名と説明を記入し、先ほどzip化したpythonフォルダをアップロード。アーキテクチャとランタイムは関数を作成したときのものを参照に選択する。必要事項を記載したら`作成`ボタンを押下する
![スクリーンショット 2022-12-18 165054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/cb90d6c8-b419-2be7-d2ff-eb082f63268b.png)
6.作成した関数の画面に戻り、一番下のレイヤーから`レイヤーの追加`ボタンを押下する
![スクリーンショット 2022-12-18 164405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/c24abc95-e6ad-3f18-703a-9d6a56baa574.png)
7.レイヤーソースはカスタムレイヤーを選択。カスタムレイヤーの下のプルダウンから先ほど作成したレイヤーとバージョンを選択して`追加`ボタンを押下する
![スクリーンショット 2022-12-18 165740.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/1b6c916c-b3fd-1671-ca98-f9bc1cd9b286.png)
8.レイヤーが追加されたことを確認する
![スクリーンショット 2022-12-19 104949.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/d7e7af8d-9fe1-15ec-3790-670a4d8f6298.png)

これでrequestsモジュールを利用できるようになります。

### 環境変数の設定
ここではDocBaseのアクセストークンやslackのWebhookURLを直接コードに記述するのを避けるために、環境変数を設定します。
環境変数について詳しく知りたい方は以下を参照してください。
参考:https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.htmlしてください。
1.lambdaの関数の設定から`環境変数`を選択。画面右側の`編集`ボタンを押下する
![スクリーンショット 2022-12-18 170535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/c8eca19e-f278-3f77-8777-ab52e2ec2f2f.png)
2.環境変数の追加ボタンを押し、キーと値の入力欄を表示する。キーに任意の名前を入れ、値に先ほど取得したDocBaseのアクセストークンとslackのWebhookURLを入力し、`保存`ボタンを押下する
![スクリーンショット 2022-12-18 174646.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/e22e5bf6-66b0-6f4e-2c84-79e6807285ec.png)
3.環境変数が追加されていることを確認する
![スクリーンショット 2022-12-18 174748.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/a4d2dff1-03cc-36be-41b8-4b3756e063f1.png)

## ⑤コードの記述
lambdaのコードソースを以下に書き換えます。
※グループ名となっているところは、実際は自分の所属する事業部名になっています。

```
import urllib3
import json
import requests
import os
from datetime import datetime, timedelta
http = urllib3.PoolManager()

def lambda_handler(event, context):
    # DocBaseのメモ検索APIを利用
    docbase_secret = os.environ['DOCBASE_TOKEN']
    headers = {"X-DocBaseToken" : docbase_secret}
    url = "https://api.docbase.io/teams/iret/posts?"
    # jstとutcの時差+9時間
    DIFF_JST_FROM_UTC = 9
    jst_yesterday = (datetime.now() - timedelta(1) + timedelta(hours=DIFF_JST_FROM_UTC)).strftime('%Y-%m-%d')
    jst_friday = (datetime.now() - timedelta(3) + timedelta(hours=DIFF_JST_FROM_UTC)).strftime('%Y-%m-%d')
    yesterday = (datetime.now() - timedelta(1) + timedelta(hours=DIFF_JST_FROM_UTC)).strftime('%Y年%m月%d日')
    friday =(datetime.now() - timedelta(3) + timedelta(hours=DIFF_JST_FROM_UTC)).strftime('%Y年%m月%d日')
    saturday = (datetime.now() - timedelta(2) + timedelta(hours=DIFF_JST_FROM_UTC)).strftime('%Y年%m月%d日')
    # 月曜日は金曜日、土曜日、日曜日の3日分を取得する
    week_num = datetime.today().weekday()
    if week_num == 0:
        params = {"q" : "group:グループ名 created_at:" + jst_friday + '~' + jst_yesterday}
        text =  '*' + friday + '~' + yesterday + 'に投稿された記事一覧です！* \n \n'
    else:
        #月曜日以外は昨日投稿された記事を取得する
        params = {"q" : "group:グループ名 created_at:" + jst_yesterday}
        text = '*' + yesterday + 'に投稿された記事一覧です！* \n \n'
        
    res = requests.get(url, headers = headers, params = params)
    if res.json()['meta']['total'] == 0:
        pass
    else:
        for item in res.json()['posts']:
            text += '<' + item['url'] + '|' + item['title'] + '：' + item['user']['name'] + '>' + '\n'
    
        #取得したデータをslackに送信
        slack_url = os.environ['SLACK_URL']
        msg = {
            "channel": "#time-keisuke",
            "username": "投稿通知ボット",
            "text": text,
            "icon_emoji": "",
        }

        encoded_msg = json.dumps(msg).encode('utf-8')
        resp = http.request('POST', slack_url, body=encoded_msg)
        print({
            "status_code": resp.status, 
            "response": resp.data,
        })
```
`params = {"q" : "group:グループ名 created_at:" + jst_yesterday}`
ここで絞込の条件を指定しています。
今回はgroupとcreated_atをパラメータに入れていますが、検索オプションは他にもあり、ここで絞込の条件を変えられます。
参照:https://help.docbase.io/posts/1827704
`text += '<' + item['url'] + '|' + item['title'] + '：' + item['user']['name'] + '>' + '\n'`では、DocBaseの検索APIを利用して記事のURL、タイトル、著者名を取得したうえで、slackのマークダウン記法を利用して、文字リンクで表示されるようにしています。


## ⑥トリガーの追加
毎日決まった時間に通知されるように、Event Bridgeをトリガーに設定します。
今回は月曜から金曜日までの昼の12:00に通知が送られるように設定します。
1.関数の概要から`+トリガーを追加`ボタンを押下する
![スクリーンショット 2022-12-18 200559.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/6f34a0cc-47a5-521d-a2d3-626d2e08d73e.png)
2.トリガーはプルダウンから`EventBridge(CloudWatch Events)`を選択し、ルールは`新規ルールの作成`を選択する。ルール名とルールの説明に任意のものを入力し、ルールタイプは`スケジュール式`を選択する。スケジュール式の下の入力欄にcron(0 3 ? * MON-FRI *)と入力して`追加`ボタンを押下する。
※cron()の引数については以下を参照してください。
参考:https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html
![スクリーンショット 2022-12-18 202125.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/18f70bb3-2411-5861-afe7-81557a294a6e.png)

## 結果
slackのチャンネル上では以下のように表示されます。
![スクリーンショット 2022-12-19 120226.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/d7fbad9a-3d96-4c24-658c-88f7dd37d999.png)
文字リンクになっているためクリックすると、DocBaseの該当記事に遷移します。
![スクリーンショット 2022-12-19 120441.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953493/4244d13d-a87e-00d4-d909-c3bdedd9e59a.png)



## あとがき
AWS lambdaで目的を持ったシステムを作成するのは今回が初めてだったため、最初は分からないことだらけでしたが、同期や先輩のサポートを受け、1か月ほどの期間でなんとか形にすることができました。
サポートをしてくださった皆様、本当にありがとうございました！
これからも、このシステムの改修に力を入れていきたいと思います！

## さいごに
`アイレット株式会社 22新卒 Advent Calendar 2022`は本日が最終日でした。
22卒の皆さん、業務と並行しながらの記事の執筆お疲れ様でした！
広報や裏方でサポートをしてくださった皆様、ここまで記事を読んでくださった皆様、そして`アイレット株式会社 22新卒 Advent Calendar 2022`を企画し、何かあったときにはすぐに対応してくれた@Michinosukeくんには、この場を借りて心から感謝を申し上げます。
本当にありがとうございました！