Clivern

A Software Engineer and Occasional Writer.

How to Create a Facebook Messenger Bot With Java

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.

Create Our Chat Bot with Java

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

Create a Facebook Page

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.

Create a Facebook App

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.

Chat with Your Bot

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!