2016年9月24日土曜日

Slack out-going Slash Commands を AWS に設定する(日本語対応済み)

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
  • Set a reminder

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(' ')

pythonで正規表現を使ってみる

0 件のコメント:

コメントを投稿