Lineボットを試してみた

巷で噂のチャットボット。
その中でもMicrosoftとLineを試してみた。
MSのBot Frameworkは、jsでかけて簡単だったけどコンソールで止まってしまった。
なので、ここではLineのBOT API Trialを記録を記載しておく。

Lineのボットは限定10000人とかにAPIを開放している。
https://business.line.me/services/products/4/introduction
限定だけど、まだまだ受け付けいっぱいになる様子はまだないね。

ビジネスアカウントとして登録していく。
色々と細かく書こうと思ったけど、記録をなくしてしまっていたのと
こちらのQiitaの記事の方がはるかにまとまっているので、そちらを貼っておく。
http://qiita.com/Arashi/items/a1a6663d3fba0947815d

自分もドコモの雑談APIを入れているので、構成的には下記の形になる

ユーザ  <=> LINE <=> LINE_BOT_API <=> 自分のサーバ <=> Docomo API

DocomoAPIはなかなかすごくて、雑談APIや質問APIなどがある。
今回は、テキストに対して質問APIにアクセスし、回答がなければ雑談APIを叩く流れにしてみた。

ちなみに、LINEのBOT APIからは下記のformatが送られてくる

stdClass Object
(
  [result] => Array
    (
      [0] => stdClass Object
        (
          [content] => stdClass Object
            (
              [toType] => 1
              [createdTime] => 1465532671092
              [from] => xxxxxxxxxx
              [location] => 
              [id] => xxxxxxxxxx
              [to] => Array
                (
                  [0] => xxxxxxxxxx
                )

              [text] => \xe3\x81\xa6\xe3\x81\x99\xe3\x81\xa8
              [contentMetadata] => stdClass Object
                (
                  [AT_RECV_MODE] => 2
                  [SKIP_BADGE_COUNT] => true
                )

              [deliveredTime] => 0
              [contentType] => 1
              [seq] => 
            )

          [createdTime] => 1465532671110
          [eventType] => 138311609000106303
          [from] => xxxxxxxxxx
          [fromChannel] => xxxxxxxxxx
          [id] => xxxxxxxxxx
          [to] => Array
            (
              [0] => xxxxxxxxxx
            )
          [toChannel] => xxxxxxxxxx
        )
    )
)

この情報を元にデータを引っこ抜いてゴニョるわけです。

<?php

class ChatBot
{
    private $_apiKey = 'DOCOMO_API_ACCESS_KEY';
    private $_contextId = '';

    public function __construct () {
        // LINEからhookしたデータを取得
        $json_string = file_get_contents('php://input');
        $jsonObj = json_decode($json_string);
        $to   = $jsonObj->{"result"}[0]->{"content"}->{"from"};
        $text =  $jsonObj->{"result"}[0]->{"content"}->{"text"};

        // 質問APIに投げる
        $response = $this->_getQuestion($text);
        if ($response === false) {
            // 質問の回答がなければ雑談にする
            $response = $this->_getDialog($text);
        }

        $this->_send($to, $response);
    }

    // 質問APIに問い合わせる
    private function _getQuestion($text) {

        $query = "APIKEY=".$this->_apiKey."&q=".urlencode($text);
        $ch = curl_init("https://api.apigw.smt.docomo.ne.jp/knowledgeQA/v1/ask?$query");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        curl_close($ch);

        $answer = json_decode($result);
        if ($answer->{"code"} === "E020010") {
            return false;
        }

        $this->_contextId = '';
        return $answer->{"message"}->{"textForDisplay"};
    }

    // 雑談APIに問い合わせる
    private function _getDialog($text) {

        $query = "APIKEY=".$this->_apiKey;
        $post_data = ["utt" => $text,];
        if (empty($this->_contextId) === false) {
            $post_data["context"] = $this->_contextId;
        }

        $ch = curl_init("https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?$query");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json; charser=UTF-8'));
        $result = curl_exec($ch);
        curl_close($ch);

        $dialog = json_decode($result);
        $this->_contextId = $dialog->{"context"};
        return $dialog->{"utt"};
    }

    private function _send($to, $text) {

        // テキストで返事をする場合
        $response_format_text = [
            'contentType'   => 1,
            "toType"        => 1,
            "text"          => $text
        ];

        // toChannelとeventTypeはすべての人で固定値。変更不要。
        $post_data = [
            "to"=>[$to],
            "toChannel" => "1383378250",
            "eventType" => "138311608800106203",
            "content"   => $response_format_text
        ];

        $ch = curl_init("https://trialbot-api.line.me/v1/events");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json; charser=UTF-8',
            'X-Line-ChannelID: xxxxx',   // 自分のやつ見てね
            'X-Line-ChannelSecret: xxxxx',  // 自分のやつ見てね
            'X-Line-Trusted-User-With-ACL: xxxxx'  // 自分のやつ見てね
            ));
        $result = curl_exec($ch);
        curl_close($ch);
    }
}

new ChatBot();

そうすると最終的にこんな感じの会話ができるように。
まぁコンテキストを設定していなからわけわかめなことも多いけど、
なかなか、勝手にお返事が返ってくるのは嬉しくて楽しい。

会話系の部分をもう少し勉強してみようと思った。