この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
おはようございます、もきゅりんです。
先日、SQSからのLambda起動でSlackメッセージ送信を実装したので、忘れないうちにまとめておきます。
やること
- LambdaからSQSにメッセージ送信する
- SQSからLambdaをイベント起動する
前提条件
- SlackのWebhook URLを取得していること
- AWS CLIインストール&設定済み
どちらも設定の記事は無数にあると思うので、説明は割愛します。
ちなみに、CLIはSQSのキューを作成するだけなので、手動で作成しても問題ありませーん。
とりあえず、投げる方から作成しちゃいましょう。
LambdaからSQSにメッセージ送信する
SQSキューの作成
CLIで作成しちゃいます。
# Que作成
aws sqs create-queue --queue-name QUENAME
"moque"というキューを作りました。
Lambdaにアタッチするロールを作成
次は、Lambdaにアタッチするロールを作成します。
大雑把にSQSFullAccessで作成します。
本来は必要最小限の権限で作成します。
適当な名前で作成します。
メッセージ送信用のLambdaの作成
一から作成で進めます。
先ほど作成したロールをアタッチするのを忘れずに。
下記のように、DirectMessgeとメンション付きメッセージとで分岐させてみます。
import os
import boto3
SLACK_CHANNEL = os.environ['slackChannel']
SLACK_ID = os.environ['slackId']
HOOK_URL = os.environ['webHook']
QUE_NAME = os.environ['queName']
def lambda_handler(event, context):
is_dm = event['IsDM']
if is_dm == 'true':
# DM
sqs = boto3.resource('sqs')
queue = sqs.get_queue_by_name(QueueName=QUE_NAME)
message = {
'channel': '@' + str(SLACK_ID),
"username": "Moqrin",
"icon_emoji": ":zap:",
'text': "これはDMです"
}
else:
# メンションメッセージ
sqs = boto3.resource('sqs')
queue = sqs.get_queue_by_name(QueueName=QUE_NAME)
message = {
'channel': SLACK_CHANNEL,
"username": "Moqrin",
"icon_emoji": ":zap:",
'text': "<@%s> これはメンションです" % (str(SLACK_ID))
}
response = queue.send_message(MessageBody='SlackMessage', MessageAttributes={
'Message': {
'StringValue': str(message),
'DataType': 'String'
},
})
環境変数を忘れずに設定します。
ちゃんとする場合は、WebHookを暗号化させて対応します。
slackIdは、「プロフィール & アカウント」から取得できます。
DMかどうかのテストをイベントテンプレート「Hello World」で作成します。
テストしてみましょう。
Queの中を見に行きましょう。
ポーリングします。
メッセージが入っていますね。
では、次はイベントでトリガーされるLambdaを作成します。
SQSからLambdaをイベント起動する
SQSイベントトリガーのLambdaの作成
また一から作成で進めます。
ロールは雑ですが、先ほど作成したものを利用します。
イベントソースに最初に作成したSQSを追加します。
下記、イベント発火するLambdaとなります。
import os
import json
import logging
import ast
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
HOOK_URL = os.environ['webHook']
SLACK_CHANNEL = os.environ['slackChannel']
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
message = event['Records'][0]['messageAttributes']['Message']['stringValue']
# 文字列を辞書型に変換
slack_message = ast.literal_eval(message)
req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
try:
response = urlopen(req)
response.read()
logger.info("Message posted to %s", slack_message['channel'])
except HTTPError as e:
logger.error("Request failed: %d %s", e.code, e.reason)
except URLError as e:
logger.error("Server connection failed: %s", e.reason)
キューに送信されたメッセージは文字列なので、辞書型に変更してjsonにします。
環境変数をこちらも設定するのを忘れずに。
保存すると、先ほどキューにいたメッセージがSlackに投げられると思います。
今度は、DMを"false"にしてみましょう。
generalにメンション付きでメッセージが届いたらOKです。
以上です、どなたかのお役に立てば幸いです。