2016年7月9日 星期六

陳僖儀機械人


昨晚弄起了一台在 AWS 的伺服器,今天在想它的用途時,決定重製 Facebook Messenger 機械人。找不到上次的代碼,唯有重寫。

開發 Facebook 相關的網頁需要用上 SSL 證書,於是到 Let's Encrypt 申請一張,花了點時間才發現很多事情都要用 sudo 才能順利安裝。之後,按照 Messenger 官網的指示及格式,寫了個 PHP 版本的「陳僖儀機械人」。目前片段只是示範,人工智能還沒有這麼聰明,就像 Siri 一樣。但足以示範不同的回應,希望公司能接到這樣的工作,期待真正實踐的機會。代碼如下:
<?php
//----------------------------------------------------------------------------------------
//  Sita Chan Bot (Facebook Messenger Bot)
//----------------------------------------------------------------------------------------
//  Written by Pacess HO
//  Copyrights 2016 Pacess Studio.  All rights reserved.
//----------------------------------------------------------------------------------------

//  Page access token
$_tokenPacessStudio = "Your access token here";

$_verifyToken = "";
$_mode = "";

//----------------------------------------------------------------------------------------
function callSendAPI($messageData)  {
   global $_tokenPacessStudio;

   //  API Url and Access Token, generate this token value on your Facebook App Page
   $url = "https://graph.facebook.com/v2.6/me/messages?access_token=".$_tokenPacessStudio;
   error_log("[FBMessengerBot] url=$url");

   //  Initiate cURL.
   $ch = curl_init($url);

   //  Tell cURL that we want to send a POST request.
   curl_setopt($ch, CURLOPT_POST, 1);

   //  Attach our encoded JSON string to the POST fields.
   curl_setopt($ch, CURLOPT_POSTFIELDS, $messageData);
   error_log("[FBMessengerBot] messageData=$messageData");

   //  Set the content type to application/json
   curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type:application/json"));

   //  Execute the request but first check if the message is not empty.
   $result = curl_exec($ch);
   error_log("[FBMessengerBot] result=$result");
   return $result;
}

//----------------------------------------------------------------------------------------
function sendTextMessage($recipientID, $messageText)  {
   $jsonData = '{
      "recipient":{
         "id":"'.$recipientID.'"
      }, 
      "message":{
         "text":"'.$messageText.'"
      }
   }';
   callSendAPI($jsonData);
}

//----------------------------------------------------------------------------------------
function sendImageMessage($recipientID)  {
   $jsonData = '{
      "recipient":{
         "id":"'.$recipientID.'"
      }, 
      "message":{
         "attachment":{
            "type":"image",
            "payload":{
               "url":"https://www.pacess.com/sita-chan-bot/images/sita.jpg"
            }
         }
      }
   }';
   callSendAPI($jsonData);
}

//----------------------------------------------------------------------------------------
function sendButtonMessage($recipientID)  {
   sendTextMessage($recipientID, "Button message is coming soon...");
}

//----------------------------------------------------------------------------------------
function sendGenericMessage($recipientID)  {
   $jsonData = '{
      "recipient":{
         "id":"'.$recipientID.'"
      }, 
      "message":{
         "attachment":{
            "type":"template",
            "payload":{
               "template_type":"generic",
               "elements":[{
                  "title":"陳僖儀與媽媽 最後一次互動",
                  "subtitle":"蘋果動新聞",
                  "item_url":"http://hk.dv.nextmedia.com/actionnews/entertainment/20130417/18231328/20013358",               
                  "image_url":"http://static.apple.nextmedia.com/images/apple-photos/apple/20130417/large/1366177517_633f.jpg",
                  "buttons":[{
                     "type":"web_url",
                     "url":"http://hk.dv.nextmedia.com/actionnews/entertainment/20130417/18231328/20013358",
                     "title":"Open Web URL"
                  }, {
                     "type":"postback",
                     "title":"Save this news",
                     "payload":"Payload for first bubble",
                  }],
               }]
            }
         }
      }
   }';
   callSendAPI($jsonData);
}

//----------------------------------------------------------------------------------------
function sendFileMessage($recipientID)  {
   $jsonData = '{
      "recipient":{
         "id":"'.$recipientID.'"
      }, 
      "message":{
         "attachment":{
            "type":"file",
            "payload":{
               "url":"https://www.pacess.com/sita-chan-bot/files/sita.pdf"
            }
         }
      }
   }';
   callSendAPI($jsonData);
}

//----------------------------------------------------------------------------------------
function sendReceiptMessage($recipientID)  {
   sendTextMessage($recipientID, "Receipt message is coming soon...");
}

//----------------------------------------------------------------------------------------
//  Webhooks functions
//----------------------------------------------------------------------------------------
function receivedAuthentication($messagingEvent)  {
   $senderID = $messagingEvent["sender"]["id"];
   $recipientID = $messagingEvent["recipient"]["id"];
   $messageTime = $messagingEvent["timestamp"];

   sendTextMessage($recipientID, "receivedAuthentication");
}

//----------------------------------------------------------------------------------------
function receivedMessage($messagingEvent)  {
   $senderID = $messagingEvent["sender"]["id"];
   $recipientID = $messagingEvent["recipient"]["id"];
   $messageTime = $messagingEvent["timestamp"];

   $messagingDictionary = $messagingEvent["message"];
   $messageID = $messagingDictionary["mid"];
   $messageSequence = $messagingDictionary["seq"];
   $messageText = $messagingDictionary["text"];
   $messageAttachments = $messagingDictionary["attachments"];

   //----------------------------------------------------------------------------------------
   //  Base on message, do different things
   $messageText = strtolower($messageText);

   $index = strpos($messageText, "hi, sita");
   if ($index !== false)  {

      $message = "";
      $hour = date('H');
      if ($hour < 10)  {$message = "Good morning, Pacess.  What can I do for you?";}
      else if ($hour < 16)  {$message = "Good afternoon, Pacess.  What can I do for you?";}
      else if ($hour < 19)  {$message = "Good evening, Pacess.  What can I do for you?";}
      else {$message = "Good night, Pacess.  What can I do for you?";}

      sendTextMessage($senderID, $message);
      return;
   }

   $index = strpos($messageText, "image");
   if ($index !== false)  {sendImageMessage($senderID);  return;}

   $index = strpos($messageText, "button");
   if ($index !== false)  {sendButtonMessage($senderID);  return;}

   $index = strpos($messageText, "news");
   if ($index !== false)  {sendGenericMessage($senderID);  return;}

   $index = strpos($messageText, "receipt");
   if ($index !== false)  {sendReceiptMessage($senderID);  return;}

   $index = strpos($messageText, "pdf");
   if ($index !== false)  {sendFileMessage($senderID);  return;}

   //----------------------------------------------------------------------------------------
   //  Send normal text message
   $index = rand(0, 3);
   switch ($index)  {
      default:
      case 0: {sendTextMessage($senderID, "OK, $messageText");}  break;
      case 1: {sendTextMessage($senderID, "Hello, $messageText");}  break;
      case 2: {sendTextMessage($senderID, "Noted, $messageText");}  break;
      case 3: {sendTextMessage($senderID, "Um...$messageText");}  break;
   }
}

//----------------------------------------------------------------------------------------
function receivedDeliveryConfirmation($messagingEvent)  {
   $senderID = $messagingEvent["sender"]["id"];
   $recipientID = $messagingEvent["recipient"]["id"];
   $messageTime = $messagingEvent["timestamp"];

   sendTextMessage($recipientID, "receivedDeliveryConfirmation");
}

//----------------------------------------------------------------------------------------
function receivedPostback($messagingEvent)  {
   $senderID = $messagingEvent["sender"]["id"];
   $recipientID = $messagingEvent["recipient"]["id"];
   $timeOfPostback = $messagingEvent["timestamp"];

   //  The 'payload' param is a developer-defined field which is set in a postback button for Structured Messages. 
   $payload = $messagingEvent["postback"]["payload"];

   $message = "Received postback for user $senderID and page $recipientID with payload '$payload' at $timeOfPostback";

   //  When a postback is called, we'll send a message back to the sender to let them know it was successful
   sendTextMessage($senderID, $message);
}

//========================================================================================
//  Main program
//----------------------------------------------------------------------------------------
if (isset($_REQUEST["hub_mode"]))  {$_mode = $_REQUEST["hub_mode"];  error_log("[FBMessengerBot] Mode=$_mode");}
if (isset($_REQUEST["hub_verify_token"]))  {$_verifyToken = $_REQUEST["hub_verify_token"];  error_log("[FBMessengerBot] verifyToken=$_verifyToken");}

//----------------------------------------------------------------------------------------
//  Set this 'Verify Token Value' on your Facebook App 
if ($_mode == "subscribe")  {
   if ($_verifyToken === "9b73938d049d7da4fdb600c4dcffe24f")  {
      $challenge = $_REQUEST["hub_challenge"];
      error_log("[FBMessengerBot] Subscribe webhook...$challenge");
      echo $challenge;
   }  else  {
      error_log("[FBMessengerBot] ### Unable to subscribe webhook...");
      echo("### Unable to subscribe service, make sure the validation tokens match...");
   }
   exit(0);
}

//----------------------------------------------------------------------------------------
echo("Processing...");

//  data = {
//      "object":"page",
//      "entry":[{
//         "id":"98765432910",
//         "time":1468058503315,
//         "messaging":[{
//            "sender":{"id":"98765432910"},
//            "recipient":{"id":"1234567890"},
//            "timestamp":1468058503251,
//            "message":{
//               "mid":"mid.1468058503242:f49cde80d52c67d427",
//               "seq":9,
//               "text":"Well"
//            }
//         }]
//      }]
//   }
$data = file_get_contents("php://input");
error_log("[FBMessengerBot] data=$data");
$jsonData = json_decode($data, true);

$object = $jsonData["object"];
if ($object == "page")  {
   foreach ($jsonData["entry"] as $pageEntry)  {

      $pageID = $pageEntry["id"];
      $timeOfEvent = $pageEntry["time"];
      $messaging = $pageEntry["messaging"];

      if (isset($messaging) == false)  {continue;}

      //  Iterate over each messaging event
      foreach ($messaging as $messagingEvent)  {
      
         if (isset($messagingEvent["message"]))  {receivedMessage($messagingEvent);  continue;}
         if (isset($messagingEvent["delivery"]))  {receivedDeliveryConfirmation($messagingEvent);  continue;}
         if (isset($messagingEvent["optin"]))  {receivedAuthentication($messagingEvent);  continue;}
         if (isset($messagingEvent["postback"]))  {receivedPostback($messagingEvent);  continue;}

         error_log("[FBMessengerBot] ### Webhook received unknown messagingEvent:$messagingEvent");
      }
   }
}

//----------------------------------------------------------------------------------------
echo("Program ended.");
?>

沒有留言: