LambdaでChatWorkのメッセージをslackに流してみました
ベルリンの半瀬です。 こんにちは。
はじめに
ベルリンチームは主にSlackでやり取りをしていますが、国内ではChatWorkが主なので、そちらの動きも追う必要があります。 行ったり来たりするのは不便なので、一部の部屋の投稿だけSlackに流す方法を探していました。 下記のZapierを使った方法などはすぐに設定ができて楽そうでした。
ChatWork→Slack連携: ChatWorkの新着通知をSlackに投稿する | atskimura-memo
ZapierのFreeプランではZap回数に制限があったりするので、流量の多い部屋だとすぐに上限に到達してしまうことや、 もう少しリアルタイム性が欲しいなーということで、試しにlambdaとcloudwatch eventで自動転記をしてみました。 (スクリプトは↑の参考URLを見本とさせていただきました(__m謝
pythonスクリプト
2.7で書きます。こんな感じ
#-*- coding: utf-8 -*- from __future__ import print_function import requests from datetime import datetime cwtoken = '787dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' sltoken = 'xoxp-4xxxxxxxxxxx-50xxxxxxxxxxxx-2xxxxxxxxxxxxxx-d65dxxxxxxxxxxxxxxxxxxxxxxxx' cwapiurl = 'https://api.chatwork.com/v2' slapiurl = 'https://slack.com/api' def lambda_handler(event, context): fromto = event['fromto'] for list in fromto: roomid = list['cwroomid'] channel = list['slchannel'] url1 = cwapiurl + '/rooms/' + roomid + '/messages' headers1 = {'X-ChatWorkToken': cwtoken } try : req1 = requests.get(url1, headers=headers1) if req1.status_code == 204 : print('204' ) else : res_json=req1.json() i = 0 l = len(res_json) - 1 while i <= l : body = res_json[i]['body'] name = res_json[i]['account']['name'] msid = res_json[i]['message_id'] time = res_json[i]['send_time'] try : text = '*' + str(datetime.fromtimestamp(time)) + ' message from: ' + name + '*\n```' + body + '```' url2 = slapiurl + '/chat.postMessage' params2 = { 'token' : sltoken, 'channel' : channel, 'text' : text, 'as_user': 'false', 'username': 'ChatWork(auto)' } req2 = requests.put(url2, params=params2) except Exception as e : print('[error][put]' + str(e)) i += 1 except Exception as e : print('[error][get]' + str(e)) if __name__ == "__main__": lambda_handler({}, {})
このスクリプトはchatwork api のトークンとslack apiのトークンが前提になっています。 chatworkはここを参考に、slackはここからそれぞれ取得しておきましょう。slack のpermission scopeは「chat:write:bot」が必要です。
注意: できないこと - slackからChatworkへの転記はできません。
スクリプトの使い方
トークンと部屋情報の記載
cwtoken
にChatworkのトークンを、sltoken
にSLackのトークンを入れます。
次に、転機元のChatwork部屋と転記先のslackチャンネルの情報が必要となりますが、fromto = event['fromto']
の様な形としておき、これはcloudwatchからJSONリスト形式で渡す様にします(後述)。
Lambda
AWS Lambdaに載せます。requestsモジュールを使っていますので、パッケージ化をしてからアップロードしましょう。
CloudWatch Eventsの設定(転送元と先の指定)
Cloudwatch 「ルール」からアップロードしたlambda関数を指定して、1分間隔での実行を指定します。 その際、「入力の設定」から「定数(JSONテキスト)」を選択し、以下を参考にJSONテキストを渡す様に指定します。
AWS CloudWach Events実行時に便利なConfigure input | Developers.IO
{ "fromto": [{ "cwroomid": "<ChatWorkルームのID>", "slchannel": "<SlackチャンネルのID>" }, { "cwroomid": "< 〃 >", "slchannel": "< 〃 >" }, { "cwroomid": "< 〃 >", "slchannel": "< 〃 >" }] }
cwroomid
に、ルームID( 例:「https://kcw.kddi.ne.jp/#!rid{{ここの数字}}」)
slchannel
にチャンネル名(例: #test1だと、「test1」)
複数ある場合は、リスト形式で追記します。「,」を忘れずに。
以下の様な形で設定します。
テスト
Chatworkに投稿
1分以内にSlackで表示。もちろん絵文字は反映されません。
終わりに
以上です。
APIの制限周りを考慮しきれていません。Chatwork APIは「5分に100回まで」という制限があるので、APIを実行するユーザーで他にAPI実行していないかどうか、気をつけてください。分間実行でもChatwork側で20部屋くらいを指定すると上限に当たる気がします。 多分そこまで使わないはず。。はず。。
参考にしたもの
Methid chat.postMessage | Slack API Rate Limits | Slack API エンドポイント: /rooms | ChatWork API ドキュメント エンドポイント: APIの利用回数制限について | ChatWork API ドキュメント
それではー