PHP chatbot フレームワーク Botmanを使ったbot開発 ~導入編~

[DMM.com #1 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/dmm)の23日目担当の@ihara-kentaです。
DMM.comのアドベントカレンダーはこちらです。
[DMM.com #1 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/dmm)
[DMM.com #2 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/dmm2)

昨日は @masami256 さんの[Linux 4.15で入ったWARN*_ONCE系マクロのカウンタクリア機能](https://qiita.com/masami256/items/5896c8b474288eb349ed)でした。みなさん雰囲気を掴めましたか？？
いよいよクリスマスが近づいてきました、Advent Calendarも終盤ですね。
明日は@y-ohgi さん、よろしくお願いします。

自分は、普段はシステム開発、保守の行っているバックエンドエンジニアのPHPerです。

今回紹介するのはPHPerによる、PHPerのためのBot Framework [BotMan](https://botman.io/) です。

今回は公式で提供されているLaravel内BoｔManを組み込んだ[BotMan Studio](https://botman.io/2.0/botman-studio)の話をメインに進めていきます。

## 対象読者
- PHPerの皆さん
- Bot作ってみたいけど、CoffeeScriptかーっとなってしまった人
- laravelもかじってみたい人
- レガシーシステムばかりでモチベーションが上がらない人

## なぜPHPでBot開発なのか
冒頭ですが、ちょっとだけエモい話になります。
普段の業務はレガシーなサービス(レガシーの定義は敢えて定義しないでおこうと思います。)の保守開発を行っているため、新規開発を行えずに技術的な向上が目に見えづらく、モチベーションがあがらない日々が続いていました。

そんな折に、10月に開催されたPHPカンファレンス2017で、自分と同様にレガシープロジェクトを抱えながらも懸命に改善を進める姿に感銘を受け、背中を押されました。

そこでチームに戻り、自分と同じような不安を抱えていたメンバーとチーム内で運営していたセミナータイプの勉強会をスモールプロジェクトの開発時間に変更することを提案しました。
チームメンバーのPHPスキル向上と新規開発の流れの習得、そして、botの業務改善でのチームへの実益の3本を兼ねることから、PHPでのbot開発を進めていくことになりました。

と、まあ、そんなこんなで見つけたのが、今回紹介する[BotMan](https://botman.io/)になります。

## BotManとは
>BotMan is a framework agnostic PHP library that is designed to simplify the task of developing innovative bots for multiple messaging platforms, including Slack, Telegram, Microsoft Bot Framework, Nexmo, HipChat, Facebook Messenger, WeChat and many more.

簡単に言うと、SlackやFacebook Messengerなど様々なチャットツールとの互換性のあるPHPで作られたbotフレームワークです。

CoffeeScriptで書くhubotが有名になりましたが、ついにPHP界でのbot作成にもデファクトスタンダードが出てきたようです。
やはり、この後紹介するLaravelのエコシステムを活用出来るようにLaravel内にBotManを取り込んだ[BotMan Studio](https://botman.io/2.0/botman-studio)の功績が大きいなと感じています。

そんな[BotMan Studio](https://botman.io/2.0/botman-studio)にフォーカスを当てていこうと思います。

## BotMan Studioとは
BotManは単体でも動作しますが、Laravelに取り込むことで、テストやチャットツールとの連携や設定を容易になり、効率の良いbot開発を行なうことが出来るようになりました。
Laravelに慣れている人にとっては、bot開発に参入しやすくなり、PHPでのbot開発を行いたい人にとってはLaravelに触れる機会が増える良い相互作用が生まれているなと感じました。

### インストール
BotMan Studioは以下の環境下で動作します。

- PHP >= 7
- OpenSSL PHP Extension
- PDO PHP Extension
- Mbstring PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension

```bash
$ composer global require "botman/installer"
$ botman new weatherbot
```
または

```bash
$ composer create-project --prefer-dist botman/studio weatherbot
```

以上のコマンドでインストールは完了です。
さっそくbot開発に移っていきましょう。

*create-project で作成すると、botman/botman(v2.0.1)がインストールされ、後のドライバーインストールがうまく動作しないことを確認出来ました。インストール後に`composer update`をおすすめします。*

### php artisan botman:tinker
インストールが完了すると、artisanコマンドに既にbotmanコマンドが用意されているので、すぐにbot開発に着手出来ます。
[BotMan Studio](https://botman.io/2.0/botman-studio)の最大のメリットとも言えるコンソールでの対話型チャットを行なうことで迅速なフィードバックサイクルが生まれます。

tinkerコマンドでbotを立ち上げて、会話を行ってみましょう。

```bash
$ php artisan botman:tinker
```
![tinker.gif](https://qiita-image-store.s3.amazonaws.com/0/147300/8fa4d67e-1b92-b474-da3d-5c8a76a92136.gif)

`~/routes/botman.php`でこのように記述されています。

```php:~/routes/botman.php
$botman->hears('Hi', function ($bot) {
    $bot->reply('Hello!');
});
```
また下記の様にすると、引数として値を受け取る事が出来ます。

```php:~/routes/botman.php
$botman->hears('Hi', function ($bot) {
    $bot->reply('Hello!');
});

$botman->hears('Hi {name}', function ($bot, $name) {
    $bot->reply("Hello $name!");
});
```
![hello.gif](https://qiita-image-store.s3.amazonaws.com/0/147300/5390d727-0861-2041-e680-7e246be42b98.gif)

### テスト
BotMan Studioではテストも簡単に実装が可能です。

`tests/Botman`ディレクトリ配下にテストを追加していきます。

```php:~/tests/BotMan/ExampleTest.php
    /**
     * Command test.
     *
     * @return void
     */
    public function testCommandTest()
    {
        $names = ['world', 'botman', 'Christmas'];
        $key   = array_rand($names);
        $name  = $names[$key];

        $this->bot
            ->receives("Hi $name")
            ->assertReply("Hello $name!");
    }
```

このように`~/tests/TestCase.php`を継承したテストクラスで、botの挙動を容易にテストすることが出来ます。

### チャットツールとの連携
チャットツールとの連携も用意に行うことが出来ます。
今回はSlackとの連携を進めてみます。

artisanコマンドの中にdriverのインストールコマンドがあるので、それを使います。
こちらは利用可能なdiverの一覧です。

```bash
$ php artisan botman:list-drivers
+--------------+-------------------------+--------------------------------------------------+------------+
| Name         | Service                 | Description                                      | Installed? |
+--------------+-------------------------+--------------------------------------------------+------------+
| amazon-alexa | Amazon Alexa            | Use BotMan with Amazon Alexa.                    | ❌          |
| cisco-spark  | Cisco Spark             | Use BotMan with Cisco Spark.                     | ❌          |
| facebook     | Facebook                | Use BotMan with the Facebook messenger platform. | ❌          |
| hipchat      | HipChat                 | Use BotMan with Atlassian HipChat.               | ❌          |
| kik          | Kik                     | Use BotMan with the Kik messenger.               | ❌          |
| botframework | Microsoft Bot Framework | Use BotMan with the Microsoft Bot Framework.     | ❌          |
| nexmo        | Nexmo                   | Use BotMan with Nexmo to send and listen to SMS. | ❌          |
| slack        | Slack                   | Use BotMan with Slack.                           | ❌          |
| telegram     | Telegram                | Use BotMan with the Telegram messenger.          | ❌          |
| twilio       | Twilio                  | Use BotMan with Twilio.                          | ❌          |
| web          | Web                     | Use BotMan with your API/Website.                | ✅          |
| wechat       | WeChat                  | Use BotMan with the WeChat messenger.            | ❌          |
+--------------+-------------------------+--------------------------------------------------+------------+
```
では、slackドライバーをインストールします。

```bash
$ php artisan botman:install-driver slack
```

正常にインストールが完了したら `weatherbot/config/botman/slack.php` が生成されていることを確認し、`.env`ファイルにslackのAPIトークンを記載します。

```:.env
SLACK_TOKEN=hogehoge
```

あとはSlackに接続して、会話します。

```bash
$ php artisan botman:listen-on-slack
Successfully connected
```

以上でBotManの導入が完了しました、あとは機能を実装して、業務ハックしていくだけです！

## まとめ
bot開発を進めることで、業務の中でも小さく始めることが出来、比較的効果の高い改善アプローチであると感じました。
BotManの登場でPHPerにもbot開発が身近なものになってきたと思います、日本語のBotMan記事はまだ少ないので、これを見てBotManへの導入に繋がれば幸いです！