20 October 2017
Today I’ll show you how to build your own Facebook Messenger Chat Bot in Java. We’ll use Spark Web Framework, Racter Java Package, Gradle and Ngrok. So Let’s get started.
We need install spark framework and set all required third party packages like racter.
$ mkdir dunk
$ gradle wrapper --gradle-version=4.0
$ nano build.gradle
and Insert the following into our build.gradle
file.
/*
* This build file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java Library project to get you started.
* For more details take a look at the Java Libraries chapter in the Gradle
* user guide available at https://docs.gradle.org/4.0/userguide/java_library_plugin.html
*/
// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'
apply plugin: 'application'
archivesBaseName = "dunk"
version = '1.0.0'
mainClassName = "com.clivern.dunk.Main"
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
dependencies {
compile 'com.sparkjava:spark-core:2.6.0'
compile 'org.slf4j:slf4j-api:1.7.13'
compile 'org.slf4j:slf4j-simple:1.7.13'
compile 'com.clivern:racter:1.0.2'
}
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Dunk ChatBot',
'Implementation-Version': version,
'Main-Class': mainClassName
}
baseName = archivesBaseName + '_fat'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Then we need to build our folder structure
$ mkdir -p src/main/java/com/clivern/dunk
$ mkdir -p src/main/java/resources
Then let’s create our main controller that has 2 end points. The first one is to verify token and the other one to process the inbound messages and events.
/*
* Copyright (C) 2017 Clivern. <https://clivern.com>
*/
package com.clivern.dunk;
import static spark.Spark.*;
import com.clivern.racter.BotPlatform;
import com.clivern.racter.receivers.webhook.*;
import com.clivern.racter.senders.*;
import com.clivern.racter.senders.templates.*;
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException
{
// Verify Token Route
get("/", (request, response) -> {
BotPlatform platform = new BotPlatform("src/main/java/resources/config.properties");
platform.getVerifyWebhook().setHubMode(( request.queryParams("hub.mode") != null ) ? request.queryParams("hub.mode") : "");
platform.getVerifyWebhook().setHubVerifyToken(( request.queryParams("hub.verify_token") != null ) ? request.queryParams("hub.verify_token") : "");
platform.getVerifyWebhook().setHubChallenge(( request.queryParams("hub.challenge") != null ) ? request.queryParams("hub.challenge") : "");
if( platform.getVerifyWebhook().challenge() ){
platform.finish();
response.status(200);
return ( request.queryParams("hub.challenge") != null ) ? request.queryParams("hub.challenge") : "";
}
platform.finish();
response.status(403);
return "Verification token mismatch";
});
post("/", (request, response) -> {
String body = request.body();
BotPlatform platform = new BotPlatform("src/main/java/resources/config.properties");
platform.getBaseReceiver().set(body).parse();
HashMap<String, MessageReceivedWebhook> messages = (HashMap<String, MessageReceivedWebhook>) platform.getBaseReceiver().getMessages();
for (MessageReceivedWebhook message : messages.values()) {
String user_id = (message.hasUserId()) ? message.getUserId() : "";
String page_id = (message.hasPageId()) ? message.getPageId() : "";
String message_id = (message.hasMessageId()) ? message.getMessageId() : "";
String message_text = (message.hasMessageText()) ? message.getMessageText() : "";
String quick_reply_payload = (message.hasQuickReplyPayload()) ? message.getQuickReplyPayload() : "";
Long timestamp = (message.hasTimestamp()) ? message.getTimestamp() : 0;
HashMap<String, String> attachments = (message.hasAttachment()) ? (HashMap<String, String>) message.getAttachment() : new HashMap<String, String>();
platform.getLogger().info("User ID#:" + user_id);
platform.getLogger().info("Page ID#:" + page_id);
platform.getLogger().info("Message ID#:" + message_id);
platform.getLogger().info("Message Text#:" + message_text);
platform.getLogger().info("Quick Reply Payload#:" + quick_reply_payload);
for (String attachment : attachments.values()) {
platform.getLogger().info("Attachment#:" + attachment);
}
String text = message.getMessageText();
MessageTemplate message_tpl = platform.getBaseSender().getMessageTemplate();
ButtonTemplate button_message_tpl = platform.getBaseSender().getButtonTemplate();
ListTemplate list_message_tpl = platform.getBaseSender().getListTemplate();
GenericTemplate generic_message_tpl = platform.getBaseSender().getGenericTemplate();
ReceiptTemplate receipt_message_tpl = platform.getBaseSender().getReceiptTemplate();
if( text.equals("text") ){
message_tpl.setRecipientId(message.getUserId());
message_tpl.setMessageText("Hello World");
message_tpl.setNotificationType("REGULAR");
platform.getBaseSender().send(message_tpl);
}else if( text.equals("image") ){
message_tpl.setRecipientId(message.getUserId());
message_tpl.setAttachment("image", "http://techslides.com/demos/samples/sample.jpg", false);
message_tpl.setNotificationType("SILENT_PUSH");
platform.getBaseSender().send(message_tpl);
}else if( text.equals("file") ){
message_tpl.setRecipientId(message.getUserId());
message_tpl.setAttachment("file", "http://techslides.com/demos/samples/sample.pdf", false);
message_tpl.setNotificationType("NO_PUSH");
platform.getBaseSender().send(message_tpl);
}else if( text.equals("video") ){
message_tpl.setRecipientId(message.getUserId());
message_tpl.setAttachment("video", "http://techslides.com/demos/samples/sample.mp4", false);
platform.getBaseSender().send(message_tpl);
}else if( text.equals("audio") ){
message_tpl.setRecipientId(message.getUserId());
message_tpl.setAttachment("audio", "http://techslides.com/demos/samples/sample.mp3", false);
platform.getBaseSender().send(message_tpl);
}
return "ok";
}
return "bla";
});
}
}
Then we need to create our config.properties
file that contains our facebook app settings and some additional settings for racter package.
$ nano src/main/java/resources/config.properties
It should look like the following. In the next steps, we will know how to get app_id
, verify_token
and page_access_token
app_id=app id here
verify_token=verify token here
page_access_token=access token here
log_console_status=false
log_console_level=ALL
log_file_status=false
log_file_level=ALL
log_file_path=src/main/java/resources/app.log
log_file_limit=1
log_file_count=200000
log_file_append=true
Now Our App is good to go. Open two terminals one to run our app and another to create a secure web tunnel to localhost & port 4567 with ngrok
$ ./gradlew run
$ ngrok http 4567
We need to create a Facebook Page if you don’t already have one because In order to communicate with your chat bot, people will need to go through your page.
Go to the Facebook Developer Page and click “Skip and Create App ID” at the top right. Then create a new Facebook App for your chat bot and give your app a name and contact email.
You can get the app id and insert that id in config.properties
file you created before on java app.
From the Messenger settings for your Facebook App, You can connect your app with the facebook page to get access token.
Then we need to setup our webhook like the following:
Please note that, You can set Verify Token to be any value and pass that value to our config.properties
file and restart our app (Just stop it and run ./gradlew run
).
Then click Verify and Save. Now Our Webhook should be look like the following
After you’ve configured your webhook, Just subscribe to the specific page you want to receive message notifications for.
Go to the Facebook Page you created and click on “Message” button. This should open a message pane with your Page. Start sending your Page messages and the bot should reply!
To Check The Full Code! To Check All Features that Racter Supports or Help Us Make it Much More Better!