やったこと
DocBase APIとslack WebhookURLを利用してAWS lambdaで、1日前(月曜日だけは金、土、日曜日の3日間)にDocBaseの自分が所属する事業部宛に投稿された記事を取得して、slackに通知するシステムを作成しました。
背景
以下の記事に書かれている通り、DocBaseのオーナー管理者権限を持っていればDocBaseのWebhookURLを利用して簡単にslackと連携することができます。
今回、私は上記の権限がなかったため、DocBaseのメモ検索APIをlambdaで呼び出し、slackのwebhookURLを利用して通知するシステムを作成しました。
この先、同じようなシステムを作りたいという人が現れた際に、この記事が少しでもお役に立てれば幸いです。
手順
①slackのWebhookURL発行
1.slack API( https://api.slack.com/apps )にアクセスする
2.Create an App
を押して、From scratch
を選択する
3.App Nameに任意の名前を付け、Pick a workspace to develop your app in:からワークスペースを選択して、create App
を押す
4.作成したアプリの設定画面に遷移し、右下にあるPermissions
を選択する
5.ページ中部にあるScopesの中のAdd an OAuth Scope
を押下し、出現したプルダウンからchat:write
を選択する
6.左サイドバーのApp Home
から、App Display NameのEdit
を選択する
7.Display Name(Bot Name)にbotの表示名を、Default usernameにユーザー名を入れてAdd
を選択する
8.slackに移動して通知botを導入したいチャンネルを右クリックし、チャンネル詳細を表示する
を選択する
9.インテグレーション
を選び、Appカテゴリ内にあるアプリを追加する
を押下する
10.検索窓で先ほど作ったbot名を入れ検索。下に表示されたbotの追加
を押下する
※画像では既に追加済みのため、「表示する」ボタンになっている
11.チャンネルにbotが追加されたことを確認する
12.slackAPI設定画面に戻り、左サイドバーのIncoming Webhook
を選択、Activate Incoming WebhooksをOn
にしてAdd New Webhook to Workspace
を押下する
13.botの投稿先を聞かれるため、プルダウンから投稿したいチャンネルを選択して許可する
ボタンを押下する
14.WebhookURLが発行されたことを確認する
ここで発行したWebhookURLはlambdaからメッセージを送信する際に使用します。
②DocBaseのアクセストークンを発行
1.DocBaseのアカウント設定のページを開き、サイドバーにあるアクセストークン
を選択する
2.トークンを作成
を選択する
3.任意の名前と有効期限を入力して作成
ボタンを押す
※有効期限は特に必要なければ空欄でOK
4.表示されたアクセストークンをコピーする
ここで作成したアクセストークンはDocBaseAPIを利用する際に使用します。
③lambdaの設定
1.AWSコンソールにログインして、リソースの中からlambda
を選択する
2.画面右側にある関数の作成
ボタンを押下する
3.関数の作成画面で「一から作成」を選択。任意の関数名を付け、ランタイム(使用する言語)とアーキテクチャを選択し、右下の関数を作成
ボタンを押下する
※今回ランタイムはpython3.9、アーキテクチャはx86_64を選択している
4.関数が正常に作成されたのを確認する
④コードを記述する前の下準備
DocBaseのAPIを利用する際とslackへのメッセージ送信の際にrequestsモジュールを利用するため、コードの最初でimport requestsをします。
しかし、初期のlambdaにはrequestsモジュールが存在しないため、実行すると以下のエラーが表示されます。
そこでライブラリを追加するために以下の手順を行う必要があります。
参考: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画面に戻り、ハンバーガーメニューからレイヤー
を選択。レイヤーの作成
ボタンを押下する
5.任意のレイヤー名と説明を記入し、先ほどzip化したpythonフォルダをアップロード。アーキテクチャとランタイムは関数を作成したときのものを参照に選択する。必要事項を記載したら作成
ボタンを押下する
6.作成した関数の画面に戻り、一番下のレイヤーからレイヤーの追加
ボタンを押下する
7.レイヤーソースはカスタムレイヤーを選択。カスタムレイヤーの下のプルダウンから先ほど作成したレイヤーとバージョンを選択して追加
ボタンを押下する
8.レイヤーが追加されたことを確認する
これでrequestsモジュールを利用できるようになります。
環境変数の設定
ここではDocBaseのアクセストークンやslackのWebhookURLを直接コードに記述するのを避けるために、環境変数を設定します。
環境変数について詳しく知りたい方は以下を参照してください。
参考:https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.htmlしてください。
1.lambdaの関数の設定から環境変数
を選択。画面右側の編集
ボタンを押下する
2.環境変数の追加ボタンを押し、キーと値の入力欄を表示する。キーに任意の名前を入れ、値に先ほど取得したDocBaseのアクセストークンとslackのWebhookURLを入力し、保存
ボタンを押下する
3.環境変数が追加されていることを確認する
⑤コードの記述
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.関数の概要から+トリガーを追加
ボタンを押下する
2.トリガーはプルダウンからEventBridge(CloudWatch Events)
を選択し、ルールは新規ルールの作成
を選択する。ルール名とルールの説明に任意のものを入力し、ルールタイプはスケジュール式
を選択する。スケジュール式の下の入力欄にcron(0 3 ? * MON-FRI *)と入力して追加
ボタンを押下する。
※cron()の引数については以下を参照してください。
参考:https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html
結果
slackのチャンネル上では以下のように表示されます。
文字リンクになっているためクリックすると、DocBaseの該当記事に遷移します。
あとがき
AWS lambdaで目的を持ったシステムを作成するのは今回が初めてだったため、最初は分からないことだらけでしたが、同期や先輩のサポートを受け、1か月ほどの期間でなんとか形にすることができました。
サポートをしてくださった皆様、本当にありがとうございました!
これからも、このシステムの改修に力を入れていきたいと思います!
さいごに
アイレット株式会社 22新卒 Advent Calendar 2022
は本日が最終日でした。
22卒の皆さん、業務と並行しながらの記事の執筆お疲れ様でした!
広報や裏方でサポートをしてくださった皆様、ここまで記事を読んでくださった皆様、そしてアイレット株式会社 22新卒 Advent Calendar 2022
を企画し、何かあったときにはすぐに対応してくれた@Michinosukeくんには、この場を借りて心から感謝を申し上げます。
本当にありがとうございました!