Sending structured message and keyboard menu in Viber chat bot

In this post, we will develop a Viber chat bot similar to that of chat bot of LetzCricket.

Finding Chat bot

First of all, we are going to find how the chat bot of LetzCricket looks like. For this, we need to search for a public account named LetzCricket on Viber.

You will get the screen similar the following screenshot if you enter the public chat and subscribe to the public account.

Now click on the message icon in top right side of the screen to start 1-on-1 chat. Then message “Hi” to start the conversation. As a result, you will see the following message with keyboard menu.

Now that we have a preview of what we are going to make, lets start coding. Here’s the PHP code:

<?php 
$request = file_get_contents("php://input");
$input = json_decode($request, true);
if($input['event'] == 'webhook') {
  $webhook_response['status']=0;
  $webhook_response['status_message']="ok";
  $webhook_response['event_types']='delivered';
  echo json_encode($webhook_response);
  die;
}
else if($input['event'] == "subscribed") {
  // when a user subscribes to the public account
}
else if($input['event'] == "conversation_started"){
  // when a conversation is started
}
elseif($input['event'] == "message") {
  /* when a user message is received */
  $type = $input['message']['type']; //type of message received (text/picture)
  $text = $input['message']['text']; //actual message the user has sent
  $sender_id = $input['sender']['id']; //unique viber id of user who sent the message
  $sender_name = $input['sender']['name']; //name of the user who sent the message
  
  // here goes the data to send message back to the user
if($text == 'LCNews'){
  //if user presses News option
  $data = getNewsList($sender_id);
}
elseif($text=='LCArticles'){
  //if user presses Articles option
  $data = getArticleList($sender_id);
}
elseif($text==' LCInterviews'){
  //if user presses Interview option
  $data = getInterviewList($sender_id);
}
elseif($text==' LCGallery'){
  //if user presses Gallery option
  $data = getGalleryList($sender_id);
}
elseif($text==' LCPoll'){
  //if user presses Poll option
  $data = getPollList($sender_id);
}
elseif($text==' LCPOTM'){
  //if user presses Player of the month option
  $data = getPOTM($sender_id);
}
elseif($text==' LCQuote'){
  //if user presses Quote option
  $data = getQuote($sender_id);
}
else{
  $data = getMainMenu($sender_id);
}  
  
  //here goes the curl to send data to user
  $ch = curl_init("https://chatapi.viber.com/pa/send_message ");
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
  $result = curl_exec($ch);
  curl_close($ch);
}
?>

Creating Keyboard menu

We sent normal text in the previous article. In this article, we are sending keyboard menu along with message. Keyboards can be attached to any message type and be sent and displayed together. To attach a keyboard to a message simply add the keyboard’s parameters to the message JSON. Please refer to previous article to see keyboard’s parameter.

The keyboards are fully customizable. We can create and design according to our requirement. The client will always display the last keyboard that was sent to it.

We have created a function getMainMenu() to create keyboard menu. It will be called at the same place where we had prepared content to deliver to the user.

The getMainMenu() function that delivers the main menu to the user would look like this:

<?php
function getMainMenu($user_id){
  $data['auth_token']='your_auth_token';
  $data['receiver']=$user_id;
  $data['BgColor']="#ffffff";
  $data['type']='text';
  $data['text']="Please select one of the options below:";
  
  $keyboard_array['Type']='keyboard';
  $keyboard_array['DefaultHeight']=false;
  $keyboard_array['BgColor']="#FFFFFF";
  $keyboard['keyboard']=$keyboard_array;
        
  $news['Columns']=2;
  $news['Rows']=2;
  $news['TextVAlign']="bottom";
  $news['TextHAlign']="center";
  $news['TextOpacity']="100";
  $news['Text']='NEWS';
  $news['TextSize']="regular";
  $news['ActionType']="reply";
  $news['ActionBody']="LCNews";
  $keyboard['keyboard']['Buttons'][]=$news;
  $articles['Columns']=2;
  $articles['Rows']=2;
  $articles['TextVAlign']="bottom";
  $articles['TextHAlign']="center";
  $articles['TextOpacity']="100";
  $articles['Text']='ARTICLES';
  $articles['TextSize']="regular";
  $articles['ActionType']="reply";
  $articles['ActionBody']="LCArticles";
  $keyboard['keyboard']['Buttons'][]=$articles;
  $interviews['Columns']=2;
  $interviews['Rows']=2;
  $interviews['TextVAlign']="bottom";
  $interviews['TextHAlign']="center";
  $interviews['TextOpacity']="100";
  $interviews['Text']='INTERVIEWS';
  $interviews['TextSize']="regular";
  $interviews['ActionType']="reply";
  $interviews['ActionBody']="LCInterviews";
  $keyboard['keyboard']['Buttons'][]=$interviews;
  $gallery['Columns']=2;
  $gallery['Rows']=2;
  $gallery['TextVAlign']="bottom";
  $gallery['TextHAlign']="center";
  $gallery['TextOpacity']="100";
  $gallery['Text']='GALLERY';
  $gallery['TextSize']="regular";
  $gallery['ActionType']="reply";
  $gallery['ActionBody']="LCGallery";
  $keyboard['keyboard']['Buttons'][]=$gallery; 
  $poll['Columns']=2;
  $poll['Rows']=2;
  $poll['TextVAlign']="bottom";
  $poll['TextHAlign']="center";
  $poll['TextOpacity']="100";
  $poll['Text']='POLL';
  $poll['TextSize']="regular";
  $poll['ActionType']="reply";
  $poll['ActionBody']="LCPoll";
  $keyboard['keyboard']['Buttons'][]=$poll;
  $potm['Columns']=2;
  $potm['Rows']=2;
  $potm['TextVAlign']="bottom";
  $potm['TextHAlign']="center";
  $potm['TextOpacity']="100";
  $potm['Text']='PLAYER OF THE MONTH';
  $potm['TextSize']="regular";
  $potm['ActionType']="reply";
  $potm['ActionBody']="LCPOTM";
  $keyboard['keyboard']['Buttons'][]=$potm;
  $quote['Columns']=2;
  $quote['Rows']=2;
  $quote['TextVAlign']="bottom";
  $quote['TextHAlign']="center";
  $quote['TextOpacity']="100";
  $quote['Text']='QUOTE OF THE DAY';
  $quote['TextSize']="regular";
  $quote['ActionType']="reply";
  $quote['ActionBody']="LCQuote";
  $keyboard['keyboard']['Buttons'][]=$quote;
  $website['Columns']=4;
  $website['Rows']=2;
  $website['TextVAlign']="bottom";
  $website['TextHAlign']="center";
  $website['TextOpacity']="100";
  $website['Text']='VISITE OUR WEBSITE';
  $website['TextSize']="regular";
  $website['ActionType']="open-url";
  $website['ActionBody']="http://www.letzcricket.com";
  $keyboard['keyboard']['Buttons'][]=$website;
  $data['keyboard']=$keyboard['keyboard'];
}
?>

This will show the keyboard menu with custom design.

Now if you tap the News option from the keyboard menu, a message “LCNews” is sent to the webhook. We can easily detect if a user has tapped the News option and fetch the news to send it to the user.

The function to send news list to the user is as follows:

function getNewsList($user_id){
    //fetch news array from wherever you like from your database or by calling any api
    // your news list will be something like this:
    $newsArray = array(
          'title'=>'The Title',
          'date'=>'2017-01-29',
          'link'=>'http://www.letzcricket.com',
          'image'=>' https://pbs.twimg.com/profile_images/776331737538371584/6y1GnWLP.jpg'
        );
    $keyboard_array['Type']='keyboard';
    $keyboard_array['BgColor']='#dddddd';
    for($i=0;$i<count($newsArray);$i++){
      $left['Columns']=2;
      $left['Rows']=2;
      $left['ActionType']="open-url";
      $left['ActionBody']=$newsArray[$i]['link'];
      $left['BgColor']="#ffffff";
      $left['Image']=$newsArray[$i]['image'];
      $keyboard_array['Buttons'][]=$left;
      $right['Columns']=4;
      $right['Rows']=2;
      $right['Type']="url";
      $right['TextSize']="regular";
      $right['TextHAlign']="left";
      $right['TextVAlign']="top";
      $right['ActionType']="open-url";
      $right['ActionBody']=$newsArray[$i]['link'];
      $right['BgColor']="#f5f5f5";
      $keyboard_array['Buttons'][]=$right;
    }
    $data['auth_token']='your_auth_token';
    $data['receiver']=$user_id;
    $data['BgColor']="#ffffff";
    $data['type']='text';
    $data['text']="Here are some news from LetzCricket:";
    $data['keyboard']=$keyboard_array;
}

This will display list of news back to the user like:

Similarly you can send list of articles, gallery or interviews in the format you like.

You can refer the following video for complete guidance :