書籍検索 Slash Commandsを作る

#はじめに

SlackのIntegrateまわりを使う演習としてまとめています。
Slach CommandsとWebHooksの連携まわりは
楽天ブックス書籍検索APIと連携した簡易な構成です。

# 環境

 - 楽天API
 - Slack
    -  Slash Commands
    -  Incoming WebHooks
 - 外部APIを呼ぶためのWebサーバ

# 手順

## 楽天APIでのアプリID発行
デベロッパー登録後にアプリIDを発行します

![スクリーンショット 2015-10-16 8.56.30.png](https://qiita-image-store.s3.amazonaws.com/0/12362/eb69bd46-d11a-4220-cebb-72cccb09417b.png)


APIテストフォーム：楽天ブックス書籍検索API
https://webservice.rakuten.co.jp/explorer/api/BooksBook/Search/

## Slack - Slash Commands
![スクリーンショット-2015-10-16-9.31.35.gif](https://qiita-image-store.s3.amazonaws.com/0/12362/f10d1a7a-ee94-88a9-9259-5a5ceb566a25.gif)


## Slack - Incoming WebHooks

![スクリーンショット 2015-10-16 7.53.20.png](https://qiita-image-store.s3.amazonaws.com/0/12362/5c2cac02-9df9-8a9e-d75a-2c6acaba15b1.png)

![スクリーンショット 2015-10-16 7.53.44.png](https://qiita-image-store.s3.amazonaws.com/0/12362/f4a3a7cc-4061-467b-3f3e-f5a71b05ca85.png)

設定したアイコン画像はこちらから使わせてもらいました
http://dojin-shi.info/?p=2966

## Webサーバ上にスクリプトを置く

 - SlackのSlashCommand経由で投げられたリクエストを受ける
    - Slash Commandsから受けたtokenでのフィルタリング
    - 設定されたパラメータの設定有無
 - リクエストに含まれるタイトル名を条件に楽天APIから書籍データを取得する
    - 取得データの数の制限など
 - JSONで受け取った内容から必要なパラメータ抽出
 - SlackのWebHookへ投げる
    - SlackのPayloadのフォーマットに整形
    - POSTでリクエストを送信


phpで書いてみました。

```php:index.php
<?php

require_once('settings.php');

if ($_POST['token'] != $TOKEN_SLACK_COMMAND){
    echo 'ERROR';
    return;
}

 /**
  * @see https://webservice.rakuten.co.jp/api/booksbooksearch/
  */

$data_post_rakuten = array();
$data_post_rakuten['format']='json';
$data_post_rakuten['booksGenreId']='001';
$data_post_rakuten['applicationId']= $APPLICATIONID;
$data_post_rakuten['sort']='-releaseDate';
$data_post_rakuten['size']=9; //comic only
$data_post_rakuten['hits']=10;

if ($_POST['text'] != ""){
    $data_post_rakuten['title'] = $_POST['text'];
}

$response = post_data($URL_RAKUTEN_BOOKSEARCH, $data_post_rakuten);
$result = json_decode($response,true);

//書籍data
$attachments = array();
for($itm = 0; $itm < count($result['Items']); $itm++){
    $info =  $result["Items"][$itm]["Item"];

    $attachment = array();
    $attachment["title"] = $info["title"];
    $attachment["title_link"] = $info["itemUrl"];

    $attachment["thumb_url"] = $info["largeImageUrl"];

    $attachment["fields"][0]["title"]= "発売日";
    $attachment["fields"][0]["value"]= $info["salesDate"];
    $attachment["fields"][0]["short"]= "true";

    $attachment["fields"][1]["title"]= "作者";
    $attachment["fields"][1]["value"]= $info["author"];
    $attachment["fields"][1]["short"]= "true";

    //iconだけの出力できなかった
    //$attachment["author_name"] = "楽天Webサービス";
    $attachment["author_icon"] = 'http://webservice.rakuten.co.jp/img/credit/200709/credit_7052.gif';

    $attachments[$itm] = $attachment;
}

//postdata全体
$itemInfo = array();
$itemInfo['attachments'] = $attachments;
$itemInfo['text']=  "検索:" .$_POST['text'];
$encode = json_encode($itemInfo);

$send_data = array();
$send_data["payload"]= $encode;

$response = post_data($URL_SLACK_WEBHOOK, $send_data);

echo $response;


exit;

 /**
  * @param string $url
  * @param mixed[] $data
  *
  * @return response data
  */

function post_data($url, $data){
    $postString = http_build_query($data, '', '&');

    $ch = curl_init($url);

    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);

    curl_close($ch);

    return $response;
}

?>
```

```php:settings.php

<?php
$APPLICATIONID ='';
$URL_RAKUTEN_BOOKSEARCH = 'https://app.rakuten.co.jp/services/api/BooksBook/Search/20130522';
$URL_SLACK_WEBHOOK = 'https://hooks.slack.com/services/XXXXXXX/XXXXXX/XXXXXXXXXXX';
$TOKEN_SLACK_COMMAND= 'XXXXXXXXXXXXXXXXXXXXXXXXX'

?>

```

#slackへ出力
##テキスト
画像を出すつもりが・・・
![yome.gif](https://qiita-image-store.s3.amazonaws.com/0/12362/ce484594-0fae-68b4-8e41-a433e5484dc7.gif)

リンクのみになってしまっているので、あとで調整します。検索結果が一件だけならでましたが・・・。

WebHookに返すpayloadに`attachments`を追加すると複数件ヒットした場合も画像を出すことができます。

## `attachments`を使ってレイアウト

### 例1：image_url
![スクリーンショット 2015-10-17 8.37.42.png](https://qiita-image-store.s3.amazonaws.com/0/12362/7bf6e9f0-d734-46c5-742a-d5837c8901e6.png)

### 例2：thumb_url

![スクリーンショット 2015-10-17 8.42.09.png](https://qiita-image-store.s3.amazonaws.com/0/12362/613395ec-badb-ab56-44b0-a026cc0ef3f8.png)

### 例3：fieldsとthumb_url
![スクリーンショット 2015-10-17 8.48.25.png](https://qiita-image-store.s3.amazonaws.com/0/12362/f681798e-8e6a-55c7-f85a-b9bd27817612.png)



#参考

SENDING POST DATA FROM PHP
http://www.madebymagnitude.com/blog/sending-post-data-from-php/

SlackのIncoming Webhooksのメッセージをカスタマイズ
http://qiita.com/m-nakada/items/643909ca14f306a74999

json_decode()先輩、引数渡せば連想配列になるんすね
http://d.hatena.ne.jp/ariteku/20120415/p2

Formatting
https://api.slack.com/docs/formatting

クレジット表示方法と注意
https://webservice.rakuten.co.jp/guide/credit#usage

http://www.phpdoc.org

#さいごに
タイトルでの検索が固定でよければ、直接楽天APIを叩くようSlashCommandに書くのが簡楽です。
自前のWebサーバを使う今回のような場合は

 - あまり使わない言語レベルでのはまり（phpは4以来かもとか）
 - サーバの設定（SSLを使いたいとか）
 - コード上の調整（tokenでリクエストの制限など、なんか汚い）

これらが実装のネックになりました。
おもったよりは、お手軽でした。