AWS（Lambda、EC2）とChatWorkを繋いで、Bot操作やマージリクエスト（Gitlab）を通知する仕組み紹介（業務効率化）

弊社ではChatworkを最近導入しております。
とりあえず、やりたいことの一部だけですが、ChatworkでBotを作って色々自動化や便利なことをやらせたりしていきたいと思います。
ChatworkではSlackと同様でAPIにて連携ができるので結構Botは作りやすいです。
（でもSlackに比べると結構連携はめんどくさかったりする）

# やりたいこと

1. 特定のコマンド入力から結果の出力
 - コマンド一覧をみれるようにする
 - コマンドの引数を複数解析する
 - Chatwork上でインタラクティブに処理を行う

1. GitlabにPushされたものをフックして通知する（マージリクエスト） 
 - めんどくさいソースチェックお願い処理を自動化する

他にも色々と使い所はあると思いますし、実は他にも色々やっておりますｗ
紹介する方法は一部となってます！
（むしろ色々な使用方法を聞きたいので、コメントください！）

# ChatworkAPIについて

結構検索すると色々でてくるので、かんたんに紹介。
Chatworkの機能をAPIを用いて自分のサービスやアプリケーションからChatworkの特定のRoomに投稿できたり、情報を取得したり色々できます。
ただし、APIの呼び出し回数に制限があり、***5分あたり100回まで***となっているそうです。

- [ChatworkAPIのドキュメント](http://developer.chatwork.com/ja/index.html)
- [ChatworkAPI利用申請画面](https://www.chatwork.com/login.php?redirect=apply_beta&package=chatwork&subpackage=api&args=)

# 導入＆実装

うちでは***にゃごぴー***というBotを使用して様々な通知をさせております。
ちなみに、にゃごぴーはこの子。
![nyagopi_icon.jpg](https://qiita-image-store.s3.amazonaws.com/0/52154/0a1904a7-3ddb-9828-f5c1-760168a58634.jpeg)


## 特定のコマンド入力から結果の出力

こちらで使う技術はこちら

- node.js
- hubot
- yoman
- chatwork adaptor

となっております。
node.jsの導入については各自やってもらえればOKですが、自分が参考にしたサイトはこちら。
nodebrewを入れるとめっちゃ便利。

- [nodebrew導入参考](http://qiita.com/ebisennet/items/15c3c9fdb04e66db6323)

hubotはnpmからインストールしていきます。

```
npm install -g generator-hubot
```

あと、yomanを使用してテンプレを作成するので、yomanもインストールします。

```
npm install -g yo
```

できたらyomanを用いてテンプレをサクッと作成してコードを書く準備をしましょう！

```
mkdir nyagopi
cd nyagopi
yo hubot
```

色々質問してきますが、この時点では基本Enter連打でOK!
ちなみに全部終わると下記のようなフォルダ構成になります！

```
Procfile  README.md  bin  external-scripts.json  hubot-scripts.json  node_modules   package.json  scripts
```

今の時点で起動すると、コンソール上でインタラクティブに会話することができますが、今回はChatwork上で会話をしたいため、アダプターをインストールします。

```
npm install hubot-chatwork --save
```

これでアダプターが入ったので、起動するときにオプション指定してあげればChatworkに飛ぶようになります。
その際に設定項目が必要になるので、下記を設定します。

```
# nyagopi
export HUBOT_CHATWORK_TOKEN="XXXXXXXXXXXXXXXXXXXX"
export HUBOT_CHATWORK_ROOMS="XXXXXX"
export HUBOT_CHATWORK_API_RATE="350"
```

.bash_profileに書いてもいいし、そのままコマンドとして打ってもOKです。
ちなみに、
HUBOT_CHATWORK_TOKENは取得したAPIKeyを設定します。
HUBOT_CHATWORK_ROOMSは指定したChatroomになります。（Chatworkをブラウザから見たときにURLの右にあるidです）
HUBOT_CHATWORK_API_RATEは１時間あたりのAPIの回数となります。

### ソースコードを設置

今回は下記

 - コマンド一覧をみれるようにする
 - コマンドの引数を複数解析する
 - Chatwork上でインタラクティブに処理を行う

をやりたいので実際に作ってみました。
※ zipcode取得にはGoogleMapAPIを利用

```coffeescript
module.exports = (robot) ->
  # zipcode検索がインタラクティブにできるようになる
  robot.respond /zipcode (.*)/i, (res) ->
    zipcode = res.match[1]
    url = "https://maps.googleapis.com/maps/api/geocode/json?address=#{zipcode}&language=ja&sensor=false"
    if zipcode.length != 7
      res.reply "桁数がおかしいよ！"
    else
      robot.http(url)
        .header('Accept', 'application/json')
        .get() (err, rest, body) ->
          data = JSON.parse body
          if data.status == "OK"
            res.reply "(#{data.results[0].address_components[0].long_name}) #{data.results[0].address_components[3].long_name}#{data.results[0].address_components[2].long_name}#{data.results[0].address_components[1].long_name}"
          else
            res.reply "住所が見つからなかったよ！"
```

これを./scripts/zipcode.coffeeとして保存します。
複数の引数を受け取る場合は下記の用にしたらできるみたいです。

```
  robot.respond /zipcode (.*) (.*)/i, (res) ->
    hoge1 = res.match[1]
    hoge2 = res.match[2]
```

### 実行

下記コマンドを叩くことで実行が可能になります。

```
bin/hubot -a chatwork -n nyagopi
```

### おまけ

コマンド一覧も見えるようにしていきます！
※ おもしろコマンドもぞくぞく追加中
下記をscripts/commands.coffreeとして保存

```coffeescript
module.exports = (robot) ->
  robot.respond /command ls/i, (res) ->
    commands = """
      nyago zipcode [XXXXXXX] （7桁の郵便番号を入力すると、住所を返してくれるよ!）
      nyago weather [today|tommorow]（指定した日の名古屋の住所を返してくれるよ!）
      nyago stock [ateam|nikkei]（今日の株価をAteamか日経平均株価を返してくれるよ!）
      nyago la [XXX.XXX.XXX.XXX]（特定のIPアドレスを指定したらそこのLAを返してくれるよ!）
    """
    res.reply commands
```

## GitlabにPushされたものをフックして通知する（マージリクエスト）

Gitlabには便利なものがあって、WebHookというものがあります。
WebHookを用いることで、特定の動作をGitlab上でしたら、指定したURLをGitlabが叩いてくれてそこに対してリクエストを投げてくれます。
なので、今回はWebHookのURL指定にAWS APIGatewayで作成したEndpointを指定してLambdaをかませてChatworkに加工した通知を投げて行きたいと思います！

[経路のイメージ]
1. Gitlabでマージリクエスト
2. GitlabのWebHook
3. APIGateway
4. Lambda
5. Chatwork

みたいな感じです！

GitlabのWebHookドキュメントはこちら

- [GitlabのWebHookドキュメント](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md)

結構バージョンによって変わるので注意！

最初はPush通知でテストしてみたいと思います。

### LambdaでAPIGatewayのコーディング

LambdaではChatworkに飛ばす処理が必要なので、Chatworkに飛ばす処理を書いて保存します。

```javascript
'use strict';

console.log('Loading function');
var request = require('request');

exports.handler = (event, context, callback) => {
  // debug
  console.log('event', event);
  console.log('Setting type');

  // イベントの種類によって出すメッセージを出し分ける
  var msg = '';
  var roomId = '';
  var objectKind = 'push';
  //switch (event.object_kind) {
  switch (objectKind) {
    case 'push':
      // branchの形式がrefs/heads/・・・で渡ってくるので、いらない部分は消す
      var branch = event.ref.substr(11);
      msg = '(' + event.repository.name + ') ' + event.user_name + ' push to ' + branch + "\n";
      msg += event.repository.git_http_url + "\n";
      roomId = process.env.ROOM_ID_FOR_PUSH;
      break;
  }

  console.log(event.object_kind + ' Choiced');
  console.log('Setting message');

  // chatwork側に飛ばす処理
  //var roomId   = process.env.ROOM_ID;
  var apiToken = process.env.API_TOKEN;
  var options = {
    url: 'https://api.chatwork.com/v1/rooms/' + roomId +'/messages',
    headers: {
      'X-ChatWorkToken': apiToken
    },
    form : {body : msg},
    useQuerystring: true
  };

  console.log('Sending message');

  request.post(options, function (err, res, body) {
    if (!err && res.statusCode == 200) {
      context.done(null, body);
    } else {
      context.done('error', err);
    } 
  });

  console.log('Finish!');
};
```

console.logがありますが、CloudWatchでログを見るときに便利なので、残してあります。
そして、Lambdaの中に環境変数（ROOM_ID_FOR_PUSH, ROOM_ID, API_TOKEN)がありますが、これはLambdaのコードを書くところの下に***Environment variables***として入力するところがありますので、それぞれの値を指定します。

次に、APIGatewayを設定します。
かんたんに自分が設定した内容を見せていきます。
![スクリーンショット 2016-12-04 22.34.39.png](https://qiita-image-store.s3.amazonaws.com/0/52154/6e77df7e-0b94-c754-7e09-4f3c86394911.png)
lambdaを指定するところは先程作ったLambdaを指定します。
メソッドはANYでOKです。

![スクリーンショット 2016-12-04 22.35.10.png](https://qiita-image-store.s3.amazonaws.com/0/52154/37e41f3a-e6e2-70ae-895e-22e051416ec8.png)
ステージ名はなんでもOKで、重要なのはURLの呼び出しのところにあるURLです。
（これがEndpoint）

### WebHookの設定

Admin管理者の人しか操作できないので、注意です！
プロジェクトに入ると、メニューにSettingがあると思いますので、そちらからWebHookを選択します。
![スクリーンショット 2016-12-04 22.24.47.png](https://qiita-image-store.s3.amazonaws.com/0/52154/5d73d314-3ba7-35de-1a84-697400a40330.png)

TriggerにほしいEventを指定します。
（まずはPush通知のテストをします）

URLにAPIGatewayで指定したEndpointをいれてWebHookの設定を完了します。

### 結果

適当にプロジェクトにPushしてみると、Chatworkの指定した部屋にきちんと通知が来ると思います。
これで作業している人がちゃんとPushできているかGitlabを見なくても確認ができるようになりました！

### マージリクエスト通知

push通知を取得するところまではできました！
マージリクエストもAPIのレスポンス値をみると、画面で設定する各種パラメータは受け取れそうなので、こちらをうまく加工してあげればマージリクエストは作れそう！

```
[info][title]マージリクエスト[/title]
[To:{account_id}]
ソースチェックをお願いします！
https://XXXXXXXXXXXXXXXXXX
[/info]
```

ちょっと時間がなかったので、マージリクエストの実装まではできなかったm(_ _)m
残りは次回の記事で書いていきます！

# まとめ

Chatwork連携はとても便利です！
通知関連はうまくやれば業務効率化になるので、色々な通知をこちらに飛ばすようにしております！
Ex）エンジニアが気付いて対応できる仕組み（バグの通知とか）やタスクの完了してない異常検知やお遊びコマンドとかとか

では、久しぶりにガッツリ記事を書きましたがもっと定期的に発信できるようにがんばります！