LaravelでSlackのSlash Commandを使う

#はじめに
slackのslash commandの処理をlaravelで行うときの方法について、日本語の記事がほとんどなかったので紹介する。
今回は、[Spatie](https://github.com/spatie)が公開している[Laravel Slack Slash Command](https://docs.spatie.be/laravel-slack-slash-command/v1/introduction)という便利なものを使う。
以下の手順でセットアップしていこう。

#今回の目標
<img width="1205" alt="スクリーンショット 2019-02-24 20.58.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/d680670e-9744-a2bb-3c6d-d9823ebe8927.png">
slackに`/hoge test`を送信すると、
<img width="1203" alt="スクリーンショット 2019-02-24 21.01.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/5120bf50-f988-c68c-2129-064b6f0d7bb7.png">
を応答し、
<img width="1203" alt="スクリーンショット 2019-02-24 21.29.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/f197dd61-965c-1d1a-b393-2744ff8a42f9.png">
というような`test`以外の文字列を送信すると、
<img width="1194" alt="スクリーンショット 2019-02-24 22.06.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/7a13fc55-203b-0745-58d0-a457b2df83da.png">
「文字列がtestじゃない」と言って、「Hoge」と応答してくれないようにする。

#Slash Commandsの設定
これの設定については、他の方が書いた記事がいくつもあるが、せっかくなのでここで説明する。
まずは[Slash Commands](https://api.slack.com/slash-commands)にアクセスする。

リンク先から、[設定の追加]をクリックすると、以下のようなサイトに飛ぶ。
<img width="1089" alt="スクリーンショット 2019-02-24 18.56.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/3db8eb66-3f3d-4852-0576-06a555dd462c.png">
今回は /hoge というコマンド名にする。
自分で任意のコマンドを決めて、[スラッシュコマンドインテグレーションを追加する]をクリックしよう。
<img width="1071" alt="スクリーンショット 2019-02-24 19.08.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/3a0af39d-e547-228c-a280-4b3c94604140.png">
今回は最小限の設定のみを行う。メソッドはポストにして説明を進める。
POST先のURLが必要なので、ngrok等を使うなりして利用可能なURLを用意し、YOUR_URLのところに入力しよう。
トークンは、Laravel側の設定をするときに使うよ。
これらを入力したら、ページ下部の[Save Integration]をクリックして、Slash Commandsの設定は終わりだ。

#Laravel Slack Slash Commandのインストールとセットアップ
はじめに、
`$ composer require spatie/laravel-slack-slash-command`
でパッケージをインストールする。

次に、config/app.phpで

```php:config/app.php
'providers' => [
    ...
    Spatie\SlashCommand\SlashCommandServiceProvider::class,     //追加する一文
];
```
となるように一行書き加えよう。

次に、
`$ php artisan vendor:publish --provider="Spatie\SlashCommand\SlashCommandServiceProvider" --tag="config"`
を入力しよう。

次に、config/laravel-slack-slash-command.phpに変更を加える。

```php:config/laravel-slack-slash-command.php
<?php

return [

    /*
     * At the integration settings over at Slack you can configure the url to which the
     * slack commands are posted. Specify the path component of that url here.
     *
     * For `http://example.com/slack` you would put `slack` here.
     */
    'url' => 'hoge',        //URLのpathを書く
  
    /*
     * The token generated by Slack with which to verify if a incoming slash command request is valid (deprecated).
     */
    'token' => env('SLACK_SLASH_COMMAND_VERIFICATION_TOKEN','＊＊＊')     //第二引数に、先程のトークンを入力する

    /*
     * The signing_secret generated by Slack with which to verify if a incoming slash command request is valid.
     */
    'signing_secret' => env('SLACK_SIGNING_SECRET'),

    /*
     * Verify requests from slack with signing_secret signature
     */
    'verify_with_signing' => false,

    /*
     * The handlers that will process the slash command. We'll call handlers from top to bottom
     * until the first one whose `canHandle` method returns true.
     */
    'handlers' => [
        //add your own handlers here
        App\SlashCommandHandlers\Hoge::class,        //クラスのディレクトリ
        App\SlashCommandHandlers\Error::class,       //クラスのディレクトリ
        //this handler will display instructions on how to use the various commands.
        Spatie\SlashCommand\Handlers\Help::class,

        //this handler will respond with a `Could not handle command` message.
        Spatie\SlashCommand\Handlers\CatchAll::class,
        ],
    ];
```
変更点は3つ。
1つ目は、URLのpathを書くこと。これにより、Routeが自動で生成される。

2つ目は、
```php
'token' => env('SLACK_SLASH_COMMAND_VERIFICATION_TOKEN','＊＊＊')
```
の＊＊＊に、先程Slack Commandsを設定したときに発行されたトークンを入力すること。

3つ目は、

```php
'handlers' => [
   //add your own handlers here
   ここに入力
]
```
「ここに入力」というところに、処理を書く予定のクラスのディレクトリを記述すること。
今回は`App\SlashCommandHandlers`というディレクトリを作り、その中に`Hoge.php`と`Error.php`を用意した。
ここで重要なのは、**記述する順番**である。
**上にあるクラスから順に呼ばれていくことを覚えておこう！**
以上でLaravel Slack Slash Commandのセットアップは終わりだ。

#クラスの書き方
classの説明をしていこう。

```php:app/SlashCommandHandlers/Hoge.php

<?php
namespace App\SlashCommandHandlers;

use App\SlashCommand\BaseHandler;
use Spatie\SlashCommand\Request;
use Spatie\SlashCommand\Response;

class Hoge extends BaseHandler
{
    /**
     * If this function returns true, the handle method will get called.
     *
     * @param \Spatie\SlashCommand\Request $request
     *
     * @return bool
     */
    public function canHandle(Request $request): bool
    {
        if ($request->text == test) return true;
    }

    /**
     * Handle the given request. Remember that Slack expects a response
     * within three seconds after the slash command was issued. If
     * there is more time needed, dispatch a job.
     * 
     * @param \Spatie\SlashCommand\Request $request
     * 
     * @return \Spatie\SlashCommand\Response
     */
    public function handle(Request $request): Response
    {
        return $this->respondToSlack("Hoge");
    }
}
```

```php:app/SlashCommandHandlers/Error.php
<?php
namespace App\SlashCommandHandlers;

use Spatie\SlashCommand\Request;
use Spatie\SlashCommand\Response;
use Spatie\SlashCommand\Handlers\BaseHandler;

class Error extends BaseHandler
{
    /**
     * If this function returns true, the handle method will get called.
     *
     * @param \Spatie\SlashCommand\Request $request
     *
     * @return bool
     */
    public function canHandle(Request $request): bool
    {
        return True;
    }

    /**
     * Handle the given request. Remember that Slack expects a response
     * within three seconds after the slash command was issued. If
     * there is more time needed, dispatch a job.
     *
     * @param \Spatie\SlashCommand\Request $request
     *
     * @return \Spatie\SlashCommand\Response
     */
    public function handle(Request $request): Response
    {
        return $this->respondToSlack("string is not 'test'");
    }
}

```

###`$request`について
```
token=＊＊＊
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
user_id=U2147483697
user_name=Steve
command=/hoge
text=test
response_url=https://hooks.slack.com/commands/1234/5678
```
という構成の**Request型**のデータになっている。

###`canHandle`について
先程、`config/laravel-slack-slash-command.php`には、`Hoge.php`, `Error.php` の順で記述した。
つまり、どのように動いているかというと、

* `Hoge.php`の`canHandle`がTrue →　`Hoge.php`の`handle`を実行する
* `Hoge.php`の`canHandle`がFalse→　`Error.php`を呼ぶ

というような感じで、`canHandle`が線路の分岐器のような役割をしている。
戻り値は必ず、**bool型**になるように記述する必要がある。
今回は、`Hoge.php`の`canHandle`を

```php
public function canHandle(Request $request): bool
{
   if($request->text == 'test') return true;
   return False;
}
```
と記述し、slackで`/hoge ***`を送信するとき

* ***がtest 　　　→　`Hoge.php`の`handle`を実行し、「Hoge」をslackで応答させる
* ***がtest以外　 →　`Error.php`を呼び、「string is not test」をslackで応答させる

という感じになっている。

###`handle`について
ここにはslackの送信に対する応答を記述する。基本的には、

```php
public function handle(Request $request): Response
{
   return $this->respondToSlack("***");
}
```
***を任意の文字列にすることで、slackの応答を自分好みに設定できる。
今回は「Hoge」と「string is not test」をそれぞれ応答するように設定している。

#ちゃんとできているか確認してみよう
<img width="1205" alt="スクリーンショット 2019-02-24 20.58.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/722ecaa9-28e9-8b71-279c-6c0874d14d76.png">
<img width="1203" alt="スクリーンショット 2019-02-24 21.01.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/758b28e3-f04d-7f3b-f724-e34f4a54f1b6.png">
***
<img width="1203" alt="スクリーンショット 2019-02-24 21.29.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/83bb541f-1901-43cc-e52a-decbc2fa4766.png">
<img width="1194" alt="スクリーンショット 2019-02-24 22.06.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/349288/fe889939-8de2-9fc7-19c3-93038ac131e7.png">

***
という感じで応答してくれるはずだ。

#おわりに
何かわからない点などあれば、お気軽にどうぞ。