API Gatewayを使ってSlackの書き込みをChatWorkに連携する

チャットツールとしてChatWorkとSlackを併用しているのですが、業務では個人的にSlackをあまり利用していません。 しかし、何か連絡が来た時に気づかないと困るという状況でした。

たまにしか見ないものに意識を使うのもなんなので、普段意識を使うチャットツールを1本に絞るため、SlackのメッセージをChatWorkに流してみます。

構成

少々変則的ですが、以下の構成でSlackのメッセージをChatWorkに連携します。 スクリーンショット 2017-09-21 17.06.33

  1. SlackのOutgoing WebHooksでAPI Gateway1にメッセージを送信(API Gateway1)
  2. Slackから値を受け取る(API Gateway1)
  3. 値をJSONに変換しAPI Gateway2に送信(API Gateway1)
  4. 変換された値を受け取り検証する(API Gateway2)
  5. JSONをChatWorkのAPIで受け取れる値に変換し、ChatWorkに送信(API Gateway2)

API Gatewayを2つ利用しているのは、

  • Slackから送信されるtokenの検証をしたい
  • SlackからはデータがJSONで送信されない
  • JSONでないとJSON Schemaで検証できない

といった理由から、API Gateway1でJSONに変換してAPI Gateway2でTokenの検証をしているためです。 (tokenの検証をJSON schemaのバリデーションで対応するのはどうだろう?とも思いますが、今回はとにかく簡単にやりたいのでこのようにしています。)

本記事でAPI Gatewayを2つ利用している仕組みについては、以下の記事でも記載しています。

API Gatewayを2つつないでJSON以外の値をJSON Schemaでバリデーションしてみた

やってみる

以下の流れで設定していきます。

  1. API Gateway2の設定(ChatWorkへデータを送信するAPI Gateway)
  2. API Gateway1の設定(Slackからデータを受け取るAPI Gateway)
  3. SlackのOutgoing WebHooksの設定
  4. SlackのtokenをAPI Gateway2に設定

1. API Gateway2の設定

API Gateway1からAPI Gateway2に接続する設定をする必要があるため、先にAPI Gateway2を設定します。

APIを作成し、POSTメソッドを設定

以下の設定でPOSTメソッドを設定します。

  • integration type:HTTP
  • Endpoint URL:https://api.chatwork.com/v2/rooms/[room_id]/messages

room_idにはChatWorkのグループチャットのURLより、https://kcw.kddi.ne.jp/#!ridXXXXXXのXXXXXXの部分を指定します。

スクリーンショット 2017-09-22 16.18.33

モデルの作成

API Gateway1から送信されるデータに合わせてモデルを作成します。 Content typeにはapplication/jsonを、Model schemaには以下を設定します。

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "",
  "type": "object",
  "properties": {
    "token": {
        "enum" : ["XXXXXXX"]
    },
    "team_id": {
      "type": "string",
      "minLength": 1
    },
    "team_domain": {
      "type": "string",
      "minLength": 1
    },
    "service_id": {
      "type": "string",
      "minLength": 1
    },
    "channel_id": {
      "type": "string",
      "minLength": 1
    },
    "channel_name": {
      "type": "string",
      "minLength": 1
    },
    "timestamp": {
      "type": "string",
      "minLength": 1
    },
    "user_id": {
      "type": "string",
      "minLength": 1
    },
    "user_name": {
      "type": "string",
      "minLength": 1
    },
    "text": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "token",
    "team_id",
    "team_domain",
    "service_id",
    "channel_id",
    "channel_name",
    "timestamp",
    "user_id",
    "user_name",
    "text"
  ]
}

Slackから送信されたリクエストのみを受け付ける値をJSON schemaによって検証しています。 tokenの値はSlackの設定後に設定し直します。

こちらのスキーマはjson-schema-generatorによって生成したものを元にしています。

スクリーンショット 2017-09-22 16.28.40

Method Requestの設定

API Gateway2のMethod Requestを設定します。 リクエストの検証を本文の検証に設定し、コンテンツタイプapplication/jsonのモデルに先ほど作成したモデルを設定します。 スクリーンショット 2017-09-22 16.34.51

Integration Requestの設定

API Gateway2のIntegration Requestを設定します。

Http Headersに以下の値を設定します。

  • X-ChatWorkToken:チャットワークのAPIキー
  • Content-Type:'application/x-www-form-urlencoded'

※どちらの値もシングルクオートでくくる必要があります。

スクリーンショット 2017-09-22 16.38.33

application/x-www-form-urlencodedのマッピングテンプレートを定義し、以下の値を設定します。

body=[info][title]${input.path('$.user_name').toString()}[/title]${input.path('$.text').toString()}[/info]

ChatWorkのメッセージ記法に合わせて、メッセージの投稿者とメッセージ本文を設定しています。 こちらの値を変更することで、ChatWorkに連携する情報の種類やメッセージのフォーマットを変更できます。

ChatWorkのメッセージ記法の詳細はこちらをご確認ください。

設定が完了したら、APIをデプロイし作成したエンドポイントのURLをメモしておきます。(API Gateway1の設定で使います。)

2. API Gateway1の設定

Slackから値を受け取るAPI Gateway1の設定をします。

APIを作成し、POSTメソッドを設定

以下の設定でPOSTメソッドを設定します。

  • integration type:HTTP
  • Endpoint URL:API Gateway2のエンドポイント

Integration Requestの設定

Http Headersに以下の値を設定します。

  • Content-Type:'application/json'

※'application/json'はシングルクオートでくくる必要があります。 スクリーンショット 2017-09-22 20.41.59

application/x-www-form-urlencodedのマッピングテンプレートを定義し、以下の値を設定します。

{
#set( $tmpstr = $input.body )
#foreach( $keyandvaluestr in $tmpstr.split( '&' ) )
#set( $keyandvaluearray = $keyandvaluestr.split( '=' ) )
        "$keyandvaluearray[0]" : "$keyandvaluearray[1]"#if( $foreach.hasNext ),#end
#end
}

Slackから送信される値は「token=XXXXXXXX&user_name=inabajun&text=hello....」のような形式ですが、これをJSON形式に変換しています。

設定が完了したら、APIをデプロイし作成したエンドポイントのURLをメモしておきます。(Slack側の設定で使います。)

3. SlackのOutgoing WebHooksの設定

左メニューのAppsを選択し、Browse AppsにてOutgoing WebHooksを選択

スクリーンショット 2017-09-10 23.24.11

Add Configrationを選択

スクリーンショット 2017-09-10 23.24.34

Add Outgoing WebHooks integrationを選択

スクリーンショット 2017-09-21 17.42.14

Integration Settings

以下の値を設定します。

  • Channel:Slackから連携したいChannelを選択
  • URL(s):API Gateway1のエンドポイントを設定

また、Integration Settings内に表示されるtokenの値をメモしておきます。

4. SlackのtokenをAPI Gateway2のモデルに設定

API Gateway2のモデル仮の値にしていたtokenを、SlackのOutgoing WebHooksにて払い出された値で再設定します。

以下のXXXXXXXを、Slackで生成されたtokenの値に再設定します。

    "token": {
        "enum" : ["XXXXXXX"]
    },

再度API Gateway2をデプロイしたら設定完了です。

試してみる

Slackで設定したChannelにメッセージを入力します。

スクリーンショット 2017-09-29 12.43.57

ChatWorkにメッセージが連携されました。

スクリーンショット 2017-09-29 12.44.03

ChatWork→Slackはこちら

LambdaでChatWorkのメッセージをslackに流してみました

注意

ChatWork→Slackの記事でも紹介されていますが、ChatWorkのAPIは呼び出し回数に「5分あたり100回まで」という制限があります。 参考:エンドポイント - チャットワークAPIドキュメント

Slackに5分以内100回以上メッセージを送ったり、他にもAPIを利用していると上限に達してしまう可能性が十分にありますので、あまり使わないChannelや、日報のようなメッセージの数が決まっているChannelでの使用が現実的かと思います。

私からは以上です。