วันอาทิตย์ที่ 28 พฤษภาคม พ.ศ. 2560

มาลองทำ Line Chat Bot กัน

          Line เปิดให้บริการ Messaging API มาระยะนึงแล้วแต่ก็ยังไม่ได้ลองเขียน ChatBot สักที ครั้งนี้ก็เลยมาลองเขียนดูบ้าง
             Messaging API สามารถส่งข้อความไปยังผู้ใช้ได้ ส่งข้อความโต้ตอบผู้ใช้ ซึี่งรูปแบบข้อความความสามารถอยู่ในรูปแบบ rich content ได้ เช่น image, audio, video, button, carousel เป็นต้น เราสามารถใช้ rich content โต้ตอบกับผู้ใช้ได้ เช่น สั่งซื้อสินค้า, แนะนำสถานที่โดยใช้ location ของผู้ใช้, บริการแปลภาษา ฯลฯ
          สำหรับ LINE Bot SDK มีให้เลือกใช้หลายภาษา :) มาลองเล่นกัน อันดับแรกต้องมี LINE@ account จากนั้นสั่ง Enable Messanging API ให้เรียบร้อย
         มาสร้างส่วน Webhook กัน LINE มีข้อกำหนดเรื่อง https เราใช้ PaaS อย่าง Heroku ที่มาพร้อมกับ https จะช่วยได้มาก

mkdir -p linebot/web
cd linebot
composer require php
composer require linecorp/line-bot-sdk
composer require monolog/monolog
echo "vendor/" > .gitignore
echo "web: vendor/bin/heroku-php-apache2 web/" > Procfile
echo " web/index.php
git init
git add . && git commit -am "init"
heroku create
git push heroku master
จากนั้นสั่ง
heroku open

        จะพบว่า heroku เปิดหน้า phpinfo มาถูกต้อง ให้ copy url ไปใส่ใน Webhook URL ในหน้าตั้งค่า Messaging API ให้ถูกต้อง
สั่ง config heroku ให้บันทึก ACCESS_TOKEN และ CHANNEL_SECRET ลงใน ENV ดังนี้
heroku config:set LINEBOT_ACCESS_TOKEN=XXXXXXXXX
heroku config:set LINEBOT_CHANNEL_SECRET=XXXXXXXXX

แก้ไฟล์ index.php เพิ่มโค้ดลงไปดังนี้

require_once '../vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
$logger = new Logger('LineBot');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG));
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($_ENV["LINEBOT_ACCESS_TOKEN"]);
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => $_ENV["LINEBOT_CHANNEL_SECRET"]]);
$signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
try {
$events = $bot->parseEventRequest(file_get_contents('php://input'), $signature);
} catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true));
}
view rawindex.php hosted with ❤ by GitHub
แล้วสั่ง commit และ push ใหม่ โค้ดข้างต้นจะอ่าน Webhook Events ที่ได้รับมาจาก Line App เราจะอ่าน Events เหล่านี้มาสร้าง Bot กัน Events ที่เราจะเจอบ่อยๆ เช่น MessageEvent คือข้อความที่ส่งมาจากผู้ใช้ และ Postback Event คือ action ที่เกิดจากผู้ใช้ส่งกลับมาให้ Webhook เป็นต้น แนะนำให้เปิด Line Bot SDK กับ API Reference เอาไว้ดูตอนเขียนด้วยนะครับจะได้ไม่งง
เพิ่มโค้ดเพื่อตรวจสอบ Message Events ดังนี้
require_once '../vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
$logger = new Logger('LineBot');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG));
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($_ENV["LINEBOT_ACCESS_TOKEN"]);
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => $_ENV["LINEBOT_CHANNEL_SECRET"]]);
$signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
try {
$events = $bot->parseEventRequest(file_get_contents('php://input'), $signature);
} catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true));
}
foreach ($events as $event) {
// Postback Event
if (($event instanceof \LINE\LINEBot\Event\PostbackEvent)) {
$logger->info('Postback message has come');
continue;
}
// Location Event
if ($event instanceof LINE\LINEBot\Event\MessageEvent\LocationMessage) {
$logger->info("location -> ".$event->getLatitude().",".$event->getLongitude());
continue;
}
// Message Event = TextMessage
if (($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage)) {
// get message text
$messageText=strtolower(trim($event->getText()));
}
}
view rawindex.php hosted with ❤ by GitHub
จากโค้ดจะแยก Postback, Location Message และ TextMessage เพื่อใช้ในการเขียนโค้ดในการตอบโต้กับข้อความที่ผู้ใช้ส่งมา ลองมาดูในส่วนของ TextMessage กันก่อน เราสามารถแยก message ที่ส่งมาจากผู้ใช้โดยใช้ method getText เราจะได้ text message เอาไว้ใช้วิเคราะห์ประโยคหรือส่งไปให้ conversation service หรือ machine learning service ได้ หรือจะเอามาทำ chat bot แบบถามมาตอบไปเป็น rule base ง่ายๆ ได้เช่นกัน เพื่อให้เข้าใจการส่ง message กลับไปยังผู้ใช้ เรามาตั้ง rule base ง่ายๆ กันก่อนดังนี้
  • พิมพ์ text จะส่งข้อความในรูปแบบ text กลับไปให้
  • พิมพ์ image จะส่ง image กลับไปให้
  • พิมพ์ location จะส่ง location message กลับไปให้
  • พิมพ์ confirm จะส่ง confirm dialog กลับไปให้
  • พิมพ์ button จะส่ง dialog พร้อมปุ่ม กลับไปให้
  • พิมพ์ carousel จะส่งข้อความแบบ carousel กลับไปให้
ตัวอย่างการส่ง Text Message
$outputText = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("text message");
$bot->replyMessage($event->getReplyToken(), $outputText);
view rawindex.php hosted with ❤ by GitHub
ตัวอย่างการส่ง Image
$img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363";
$outputText = new LINE\LINEBot\MessageBuilder\ImageMessageBuilder($img_url, $img_url);
$response = $bot->replyMessage($event->getReplyToken(), $outputText);
view rawindex.php hosted with ❤ by GitHub
ตัวอย่างการส่ง Location
$outputText = new \LINE\LINEBot\MessageBuilder\LocationMessageBuilder("Eiffel Tower", "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France", 48.858328, 2.294750);
$response = $bot->replyMessage($event->getReplyToken(), $outputText);
view rawindex.php hosted with ❤ by GitHub
ตัวอย่างการส่ง Confirm
$actions = array (
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("yes", "ans=y"),
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("no", "ans=N")
);
$button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder("confim message", $actions);
$outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("confim message", $button);
$response = $bot->replyMessage($event->getReplyToken(), $outputText);
view rawindex.php hosted with ❤ by GitHub
ตัวอย่างการส่ง Button
$actions = array (
// general message action
New \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder("button 1", "text 1"),
// URL type action
New \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("Google", "http://www.google.com"),
// The following two are interactive actions
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("next page", "page=3"),
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Previous page", "page=1")
);
$img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363";
$button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder("button text", "description", $img_url, $actions);
$outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("Button template builder", $button);
$response = $bot->replyMessage($event->getReplyToken(), $outputText);
view rawindex.php hosted with ❤ by GitHub
ตัวอย่างการส่ง Carousel
$columns = array();
$img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363";
for($i=0;$i<5;$i++) {
$actions = array(
new \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Add to Cart","action=carousel&button=".$i),
new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("View","http://www.google.com")
);
$column = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder("Title", "description", $img_url , $actions);
$columns[] = $column;
}
$carousel = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder($columns);
$outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("Carousel Demo", $carousel);
view rawindex.php hosted with ❤ by GitHub
โค้ดทั้งหมด
require_once '../vendor/autoload.php';
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
$logger = new Logger('LineBot');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG));
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($_ENV["LINEBOT_ACCESS_TOKEN"]);
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => $_ENV["LINEBOT_CHANNEL_SECRET"]]);
$signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
try {
$events = $bot->parseEventRequest(file_get_contents('php://input'), $signature);
} catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true));
}
foreach ($events as $event) {
// Postback Event
if (($event instanceof \LINE\LINEBot\Event\PostbackEvent)) {
$logger->info('Postback message has come');
continue;
}
// Location Event
if ($event instanceof LINE\LINEBot\Event\MessageEvent\LocationMessage) {
$logger->info("location -> ".$event->getLatitude().",".$event->getLongitude());
continue;
}
// Message Event = TextMessage
if (($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage)) {
$messageText=strtolower(trim($event->getText()));
switch ($messageText) {
case "text" :
$outputText = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("text message");
break;
case "location" :
$outputText = new \LINE\LINEBot\MessageBuilder\LocationMessageBuilder("Eiffel Tower", "Champ de Mars, 5 Avenue Anatole France, 75007 Paris, France", 48.858328, 2.294750);
break;
case "button" :
$actions = array (
// general message action
New \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder("button 1", "text 1"),
// URL type action
New \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("Google", "http://www.google.com"),
// The following two are interactive actions
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("next page", "page=3"),
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Previous", "page=1")
);
$img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363";
$button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder("button text", "description", $img_url, $actions);
$outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("this message to use the phone to look to the Oh", $button);
break;
case "carousel" :
$columns = array();
$img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363";
for($i=0;$i<5;$i++) {
$actions = array(
new \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("Add to Card","action=carousel&button=".$i),
new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder("View","http://www.google.com")
);
$column = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder("Title", "description", $img_url , $actions);
$columns[] = $column;
}
$carousel = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder($columns);
$outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("Carousel Demo", $carousel);
break;
case "image" :
$img_url = "https://cdn.shopify.com/s/files/1/0379/7669/products/sampleset2_1024x1024.JPG?v=1458740363";
$outputText = new LINE\LINEBot\MessageBuilder\ImageMessageBuilder($img_url, $img_url);
break;
case "confirm" :
$actions = array (
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("yes", "ans=y"),
New \LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder("no", "ans=N")
);
$button = new \LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder("problem", $actions);
$outputText = new \LINE\LINEBot\MessageBuilder\TemplateMessageBuilder("this message to use the phone to look to the Oh", $button);
break;
default :
$outputText = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder("demo command: text, location, button, confirm to test message template");
break;
}
$response = $bot->replyMessage($event->getReplyToken(), $outputText);
}
}
view rawindex.php hosted with ❤ by GitHub
ที่มา Thaiopensource

ไม่มีความคิดเห็น:

แสดงความคิดเห็น