SQSからLambda(Python3.7)起動でSlackにメッセージ送信する

2019.06.06

この記事は公開されてから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"というキューを作りました。

moque

Lambdaにアタッチするロールを作成

次は、Lambdaにアタッチするロールを作成します。

setup lambda role

大雑把にSQSFullAccessで作成します。

本来は必要最小限の権限で作成します。

select policy

適当な名前で作成します。

check role

メッセージ送信用のLambdaの作成

一から作成で進めます。

先ほど作成したロールをアタッチするのを忘れずに。

setup lambdatosqs

下記のように、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を暗号化させて対応します。

sqslambda envs

slackIdは、「プロフィール & アカウント」から取得できます。

slack profile

DMかどうかのテストをイベントテンプレート「Hello World」で作成します。

lambda test

テストしてみましょう。

sqslambda test

Queの中を見に行きましょう。

que result

que message display

ポーリングします。

que polling

メッセージが入っていますね。

que message

では、次はイベントでトリガーされるLambdaを作成します。

SQSからLambdaをイベント起動する

SQSイベントトリガーのLambdaの作成

また一から作成で進めます。

ロールは雑ですが、先ほど作成したものを利用します。

lambdaslack

イベントソースに最初に作成したSQSを追加します。

event source 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にします。

環境変数をこちらも設定するのを忘れずに。

sqslambda env

保存すると、先ほどキューにいたメッセージがSlackに投げられると思います。

dm message

今度は、DMを"false"にしてみましょう。

modified test

isdm changed status

generalにメンション付きでメッセージが届いたらOKです。

mention result

以上です、どなたかのお役に立てば幸いです。

参考

Boto3 Sending Messages

AWS LambdaがSQSをイベントソースとしてサポートしました!

AWS Lambda を Amazon SQS に使用する

python3 文字列を辞書に変換