LoginSignup
6

More than 5 years have passed since last update.

LINE BOT API Trial を利用し PHP で BOT を作ってみた

Last updated at Posted at 2016-05-07

概要

BOT API Trial Account がまだ登録出来たので、遊んでみました。
http://linecorp.com/ja/pr/news/ja/2016/1320

発言すると、内容がなんであろうとおいしそうなご飯の画像を返してくる BOT を作成しました。
自鯖に BOT と画像を仕込んでいます。

動作イメージ

QS_20160505-194936.png

処理イメージ

スライド1.PNG

必要なもの

  • Line developers アカウント
  • PHP が動作し 443番ポートで https がお話しできるサーバ
    • オレオレ証明書は NG
    • Let's Encrypt は OK でした

アカウント登録

LINE Business Center から BOT API Trial Account を取得しましょう。
先着1万人限定とのことですが 2016/05/05 でもアカウント登録出来ました。
LINE developers で以下のように登録されます。

LINE developers.png

アカウント情報の確認

作成したアカウントの Channel ID, Channel Secret, MID を確認しましょう。
後々利用しますので、控えておいてください。

Callback URL の設定

アカウント情報画面右下の EDIT をクリックして Callback URL を設定します。
LINE developers2.png
この時 https にすることはもちろん、ポート番号 443 も忘れずに入れてください。
入れないと URL or port number not sepcified. となるらしいです(未検証)。

Server IP Whitelist の設定

左ペインから Server IP Whitelist をクリックし API を呼び出す時、特定ソースIPのみ許可する設定を入れます。
入れないと弾かれます。
LINE developers3.png

BOT の作成

callback.php
<?php
// BOT の Channel ID, Channel Secret, MID を入力
$channel_id = "< Channel ID >";
$channel_secret = "< Channel Secret >";
$bot_mid = "< MID >";

//変数群
$log_file = "< ログファイルのパス && ファイル名 >";
$server_url = "< ServerName >";
$document_root = "< Documentroot >";
$pic_dir = "$document_root" . "< 画像が格納されているディレクトリ >";

//time zone
date_default_timezone_set('Asia/Tokyo');

// 関数群
//ユーザ情報取得する関数
function getDisplayName($to_mid){
    global $channel_id;
    global $channel_secret;
    global $bot_mid;
    $user_profiles_url = curl_init("https://trialbot-api.line.me/v1/profiles?mids=${to_mid}");
    curl_setopt($user_profiles_url, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($user_profiles_url, CURLOPT_HTTPHEADER, array(
        "X-Line-ChannelID: $channel_id",
        "X-Line-ChannelSecret: $channel_secret",
        "X-Line-Trusted-User-With-ACL: $bot_mid"
    ));
    $user_profiles_output = curl_exec($user_profiles_url);
    $user_json_obj = json_decode($user_profiles_output);
    global $displayname;
    $displayname = $user_json_obj->contacts{0}->displayName;
    curl_close($user_profiles_url);
}

//POSTするデータを作成する関数
function create_post_data($to_mid, $post_content){
    // toChannelとeventTypeは固定値なので、変更不要。
    global $post_data;
    $post_data = [
        "to"=>[$to_mid],
        "toChannel"=>"1383378250",
        "eventType"=>"138311608800106203",
        "content"=>$post_content
    ];
}

//相手に会話する内容をPOSTする関数
function post($post_data){
    global $channel_id;
    global $channel_secret;
    global $bot_mid;
    $post_url = curl_init("https://trialbot-api.line.me/v1/events");
    curl_setopt($post_url, CURLOPT_POST, true);
    curl_setopt($post_url, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($post_url, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($post_url, CURLOPT_POSTFIELDS, json_encode($post_data));
    curl_setopt($post_url, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charser=UTF-8',
        "X-Line-ChannelID: $channel_id",
        "X-Line-ChannelSecret: $channel_secret",
        "X-Line-Trusted-User-With-ACL: $bot_mid"
    ));
    $result = curl_exec($post_url);
    curl_close($post_url);
}

// 相手からメッセージ受信
$recieve_json_string = file_get_contents('php://input');
$recieve_jsonObj = json_decode($recieve_json_string);
$to = $recieve_jsonObj->{"result"}[0]->{"content"}->{"from"};
$text = $recieve_jsonObj->{"result"}[0]->{"content"}->{"text"};
$content_type = $recieve_jsonObj->{"result"}[0]->{"content"}->{"contentType"};
$location = $recieve_jsonObj->{"result"}[0]->{"content"}->{"location"};
$op_type = $recieve_jsonObj->{"result"}[0]->{"content"}->{"opType"};
$params = $recieve_jsonObj->{"result"}[0]->{"content"}->{"params"};

//DisplayName 取得
//date, mid, displayName, text, contentType をログ出力
getDisplayName($to);
file_put_contents($log_file, date("Y/m/d H:i:s") . " mid:${to}, displayName:${displayname}, text:${text}, contentType:${content_type}" . PHP_EOL, FILE_APPEND);

//会話処理
if( $op_type === 4 ){
    // 友達登録時に会話する
    getDisplayName($params[0]);
    $response_format_text = ['contentType'=>1,"toType"=>1,"text"=>"飯テロ BOT の登録ありがとうございます, ${displayname}さん."];
    create_post_data($params[0], $response_format_text);
    post($post_data);
} else if( $op_type === 8 ){
    // ブロック時はなにもせず正常終了する
    exit(0);
} else {
    // 送信する画像をランダムで選ぶ
    // glob で取得した画像総数を max に代入し、ランダムで選ばれた配列番号を num_list に代入
    // パスを変換し、末尾に画像ファイル名を追加
    $pic_array  = glob ("${pic_dir}*.jpg");
    $max = count($pic_array);
    $num_list = array_rand(range(1,$max),1);
    $pic = str_replace($document_root,"$server_url",$pic_array[$num_list]);

    $response_format_image = ['contentType'=>2,"toType"=>1,'originalContentUrl'=>"$pic","previewImageUrl"=>"$pic"];
    create_post_data($to, $response_format_image);
    post($post_data);
}

BOT 作成時のハマりポイント

ハマったポイントがありましたので紹介します。

  • callback URL を設定したのに BOT が応答してくれない
    • callback URL 登録後、数時間経たないと反映されないようです。待ちましょう。
  • Server IP Whitelist を設定したのに BOT が応答してくれない
    • callback URL ほどではありませんでしたが、時間経過しないと反映されないようです。待ちましょう。 それでもダメなら API のレスポンスをチェックしましょう。コードの $result 変数の中身を見るとか。

拡張したくなったら

BOT API を参照ください。

最後に

ただ単にランダムで画像を返す BOT なので、あまり面白みがありませんでした。
しかし PHP を初めて触るには手頃な難易度でした。
今後は対話相手の情報や、時期に応じた内容を加味し対話するような BOT が作成できると思います。
スタンプが送られてきたら、それに近い XXX の画像を返す!とか出来たら、自分だったら面白がって何度も遊んでそうです。

また作成にあたり、下記ページを参考にさせていただきました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6