ビジネスチャットツールdirectからSORACOM Airの速度クラスを変更する

過ぎし日の[ChatOps Advent Calendar 2015](http://qiita.com/advent-calendar/2015/chatops)に空きがありましたので、さかのぼりで埋めさせて頂きました。

普段、[SORACOM Air](https://soracom.jp/services/air/)のAir SIMを検証やデモ用としてiPhone 6Sにさして `s1.minimum` で利用しているのですが、たまにブラウジング等で `s1.fast` 等に変更して利用したくなることがあります。コンソールにログインして変更するのもいいのですが、*より楽しく、簡単に*できるといいなぁということで、・・・社内で利用しているビジネス専用チャットツール「[direct](https://direct4b.com/ja/)」でSORACOM Airの速度変更を行えるようにしました。要は、**SORACOM Airの速度クラス変更をdirectでやるためのボットを作ってみた**というお話です。

# [direct](https://direct4b.com/ja/)
[direct](https://direct4b.com/ja/)は、[LisB](http://www.l-is-b.com/ja/)さんが提供するビジネス用チャットツールです。個人的には「[ゆずがっぱ](https://www.facebook.com/yuzugappa/)」のスタンプが標準で使えるのが推しの理由の一つですが、文字通り[ビジネスシーンで役立つ様々な機能](https://direct4b.com/ja/feature.html)が提供されています。また、direct専用のbot開発SDKである「*daab SDK*」による業務システムやクラウドサービスとの連携ボットの開発も可能です。

## [daab](https://direct4b.com/ja/bot/)
Node.jsベースでボット開発ができる、Hubotのdirect用拡張版です。Hubot従来機能に加えてdirectで使われる便利なスタンプ類（Yes/NO、セレクト、今ココ）や動画・画像といった添付ファイルを取り扱えることを特徴としています。[daab SDK](https://direct4b.com/ja/bot/dev/)として[GitHub](https://github.com/lisb)で公開されています。

# SORACOMボット
今回は、速度クラス変更に対応するボットとします。

## サンプルコード
基本的には、Hubotの書き方をベースにdaabならではの機能スタンプ等の要素（[ドキュメント](https://direct4b.com/ja/bot/dev/samples/starter/readme_direct.html)）を入れ込んでいきます。今回はSIMや速度クラスの選択部分で*セレクトスタンプ*の機能を使います。
SORACOMのAPIはNode.jsのSDK「[soracom](https://www.npmjs.com/package/soracom)」を作ってくださっている方がいらっしゃるので、それを利用させてもらいます。

```js:soracom.js
// Description:
//  daab for SORACOM.
//
// Commands:
//   hubot speed - change speed class

var Soracom = require('soracom'); // soracomをインポート
var soracom = new Soracom({ // soracomオブジェクト
  email: 'email',
  password: 'password'
});

module.exports = function(robot) {

  var speed_class_options = ["s1.minimum", "s1.slow", "s1.standard", "s1.fast"]; // 速度クラス
  var subscriber = { // subscriberの属性
    imsi: undefined,
    tags_name: undefined
  };

  var selectSim = function(msg) { // SIM選択のためのセレクトスタンプ（質問）を送信する関数
    soracom.post('/auth', function(err, res, auth) {
      if (!err) {
        //console.log(auth);
        soracom.defaults(auth);
        soracom.get('/subscribers', { // activeなSIMの情報を取得
          status_filter: "active"
        }, function(err, res, body) {
          //console.log(body)
          var sim_options = [];
          for (var i = 0; i < body.length; i++) {
            sim_options.push(body[i].tags.name + ' (' + body[i].imsi + ')');
          }
          return msg.send({ // activeなSIMをセレクトスタンプ（質問）を送信
            question: "SIMを選択してください",
            options: sim_options
          });
        });
      }
    });
  };

  var changeSpeedClass = function(msg, speed_class) { // 速度クラス選択のためのセレクトスタンプを送信する関数
    soracom.post('/auth', function(err, res, auth) {
      if (!err) {
        //console.log(auth);
        soracom.defaults(auth);
        soracom.post('/subscribers/' + subscriber.imsi + '/update_speed_class', { // 速度クラスを変更
          "speedClass": speed_class
        }, function(err, res, body) {
          //console.log(body)
          return msg.send({ // スタンプ付きのテキスト送信
            stamp_set: "3",
            stamp_index: "1152921507291204289",
            text: body.tags.name + ' (' + body.imsi + ') の速度クラスを「' + body.type + '」に変更しました。'
          });
        });
      }
    });
  };

  // 速度クラス変更をキーワード「speed」でスタートさせる
  robot.hear(/speed/, function(msg) {
    return selectSim(msg);
  });

  // セレクトスタンプ（回答）受信時の処理
  robot.respond("select", function(msg) {
    var select_response = msg.json.options[msg.json.response];
    if (select_response.indexOf('(') >= 0) { // SIM選択時の処理
      subscriber.tags_name = select_response.split('(')[0];
      select_response = select_response.split('(')[1];
      subscriber.imsi = select_response.split(')')[0];
      return msg.send({
        question: "速度クラスを選択してください。",
        options: speed_class_options
      });
    } else { // 速度クラス選択時の処理
      if (subscriber.imsi) {
        return changeSpeedClass(msg, select_response);
      } else {
        msg.send({ // スタンプ付きのテキスト送信
          stamp_set: "3",
          stamp_index: "1152921507291204379",
          text: "SIMが選択されていない可能性があります。"
        });
        return selectSim(msg);
      }
    }
  });
};
```

# デプロイ
## daab環境の準備
「[Cloud9を利用して3分でdaab（direct用拡張Hubot）開発環境構築](https://www.joyzo.co.jp/blog/423)」を参考に、ひとまずCloud9で試してみます。リンク元の情報からdaabのダウンロード方法等一部情報が変わっている部分がありますので、まとめ直します。

1. Redisサーバの起動（`sudo service redis-server start`）
2. 今回は「Node.js」ディレクトリ配下に、daab用ディレクトリの作成（`mkdir daab&&cd daab`）
3. daab SDKのダウンロード（`git clone https://github.com/lisb/daab-starter.git`）※バージョンは執筆時点のものです
4. daabの起動（ ./bin/hubot） → daab用directアカウントの入力 → トークンの取得
5. トークンを環境変数として書き込み（`echo export HUBOT_DIRECT_TOKEN={token} >> ~/.bashrc`）
6. 書き込んだ環境変数の有効化（`source ~/.bashrc`）
7. 再度daabの起動（`./bin/hubot`）

## PING/PONGで確認
`./bin/hubot`でdaabを起動できたら、今回設定したdaab用のアカウントをトークに招待して `ping` を試してみます。

daabが「PONG」 を返してくれればOKです。

## SORACOMボットのデプロイ
`script` ディレクトリに今回の `soracom.js` を入れます。 daabは、Node.jsのforeverの永続化要素を取り込んであるので、`./bin/hubot start` で永続化してみます（Cloud9なのでたまに落ちると思いますが、とりあえず）。daabの永続化要素「daab forever」については、[こちら](https://direct4b.com/ja/bot/dev/samples/starter/environment.html)をご覧ください。

# directからSORACOM Airの速度クラスを変更してみる
daabとのトークで、*速度クラス変更のキーワード*である「**speed**」をつぶやいてみます。すると、SIMと速度クラスをセレクトスタンプで質問されるので、選択すると、最終的に速度クラスが変更されます。
![soracom-daab.jpg](https://qiita-image-store.s3.amazonaws.com/0/43383/c9035180-b954-6b0f-ba3b-00f9319fa6d9.jpeg)

# まとめ
やはり、チャットツールが入力UIになると、**楽しいし、速い！** 今回のケースではSIMの数が多くなったりすると工夫が必要ですが、現状では実用に十分耐えられそうです。

実はこれの前に、[MESH](http://meshprj.com/jp/)のボタンタグでやっていたのです。
<img width="414" alt="IMG_4935.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/43383/c67990f6-b3d4-0e4d-f55c-765d09ff87b3.png">
しかし、ボタンを持ち歩かないといけないのと、SIMを特定の1枚だけに絞って設定に埋め込む必要があるのと、速度クラスもボタンタグの「Single」「Double」「Hold」3種類までしか紐つけできないので、イマイチ感がありました。あと、MESH SDKからSORACOM APIを直接たたこうとすると、なぜか401で認証が通らなかったのでAWS Lambda/API Gatewayを経由させていて、やはりイマイチ感でした。が、これですっきりしました！

## 免責事項
ご利用は自己責任でお願い致します。