Slackには、Postをトリガーとして、外部へのPush通信を行うことができます。 具体的には、特定の投稿があった場合に、任意のURLに対し、HTTP POSTをします。
ChannelがPublicな場合は、Outgoing WebhookとSlash Commandが使えますが、Privateな場合は、Slash Commandしか使えません。
今回は、Slash CommandをAWSに設定してみました。
参考
Slash Command
- private channelでもOK
- internetからアクセスできるSSL(公的)サーバが必要
- 3秒でレスポンスする必要がある
- それ以上かかるものは、非同期処理を行う必要がある
返信は、Slash Commandのほか、incoming webhookも使える。
- Slash Commands Style Guide
AWS上で実装する
今回は、API Gatewayを使ってサーバーレスで構築しました。
API Gatewayを使えば、Slash Commandの要件をそのまま満たすことができるのでオススメです。
処理の流れは以下です。
- Slack -> API Gateway -> Lambda -> SNS/SQS/Lambda呼び出し等 -> Lambda * N -> Slack
構築方法はこちらが詳しいです。
追加でやったこと
BluePrintが更新されたのか、一部画面が違っていました。
設定順序が変わったレベルだったので、注意して見ながらやれば、問題ないと思います。
IAMロールの設定変更箇所は、直接ポリシーを編集する手順が載っていますが、 ポリシーの追加で簡単に設定することが可能です。
細かいことですが、日本語を使う場合は、Pythonコードの最初に追加します。
# -*- coding: utf-8 -*-
日本語文字化けの解消
Slash Commandsは、複数行のPostもそのまま引数として渡してくれます。
そのままだと日本語が文字化けします。
最終的に、このような関数を作ってゴリゴリと変換するようにしましたが、よりスマートなやり方がありそうです。
def utf8_in_unicode_to_str(uni):
chars = list(map(hex, map(ord, uni)))
res = ''
for i in chars:
res += chr(int(i, 16))
return res
以下調べた内容です。
まず、日本語文字化けの対応として、API Gateway上で設定する例がありました。
ただ、特殊文字(改行など)がエラーになります。
日本語と特殊文字が混在した状態だと、APIgateway上では解決できず、当方、JavaScriptにそれほど詳しくないので、Python側で対応することにしました。
Lambda上で文字列の中身を認するには、[]で囲んでログやレスポンスで渡すのが手軽です。
>>> str = u'あ'
>>> [str]
[u'\u3042']
>>> str = 'あ'
>>> [str]
['\xe3\x81\x82']
Pythonでは、parse_qsした結果をとっていたのですが、そこで、utf-8のバイナリコードがそのままunicodeに入っていました。
#「あ」を渡すと以下のように、unicodeとして入ってしまう。
[u'\xe3\x81\x82']
parse_qsにはencode指定がなかったので、urldecodeから自分でするか、一旦parse_qsでパースしたものに対して、上記関数で、変換することにしました。
サブコマンドを実装
簡単にサブコマンドのパースを実装しました。
import re
# ```は、コードエリアのため、これも区切り文字とする
has_sub = re.search('\s|```', command_text.strip())
if has_sub is None:
sub_command = ''
args = command_text.split(' ')
else:
sub_command = command_text.strip()[0: has_sub.start()]
args = command_text.strip()[has_sub.start():].split(' ')
0 件のコメント:
コメントを投稿