Creating a chatbot to help you find your dream home

JhumanJ • March 29, 2021

laravel moovino

Spending the last 365 days pretty much locked down in my flat near Russel Square, I realized how important it was to feel good at home. As I'm moving to Paris in the coming weeks, my flatmate of 5 years has to find a new flat. And it's not easy. You can browse real estate portal such as Zoopla and Rightmove everyday, but it's incredibly time consuming. You end up always runing the same queries every day, and when you find a flat that you like, it's always too late. That's why we created Moovino. A simple alert system, you are notified only for relevant listings and almost in real time, allowing you to be the first one to visit the property.

The website is already up and running, and few users already started to use Moovino. In this article I'll explain how I'll try to make Moovino even more accessible by transforming it into a ChatBot. The end goal is to have this boat available both on the website and with our messenger page.

That's all for the background, let's get into it.

Moovino is a Laravel 8 application, and luckily there is an amazing tool to integrate chatbots within a Laravel application. It's named Botman and it was created by the CTO of Beyond Code: Marcel Pociot. I'll link all the resources I used while working in this below.

Installing Botman in the project

Requiring the package:

composer require botman/botman

Installing the web driver (there are drivers for facebook messgenger, telegram etc.):

composer require botman/driver-web

Publishing config file:

php artisan vendor:publish

Routes and controller

I added this route to routes/web.php:

// Bot
Route::match(['get', 'post'], '/botman', [App\Http\Controllers\Chatbot\BotManController::class,'handle']);

And then created the controller:

php artisan make:controller Chatbot/BotManController

Before we structure the code with nice Conversation class instances, I want to play around and test a simple chatbot. The bot is a class property of the controller, and I initiated it to use Laravel's cache. So here is what my BotmanController looks like:

<?php

namespace App\Http\Controllers\Chatbot;

use App\Http\Controllers\Controller;
use BotMan\BotMan\BotManFactory;
use Illuminate\Http\Request;
use BotMan\BotMan\Cache\LaravelCache;

class BotManController extends Controller
{
    protected $bot;

    public function __construct() {
        $this->bot = BotManFactory::create([], new LaravelCache());
    }

    public function handle()
    {
        $this->bot->hears('{message}', function ($bot, $message) {
            $bot->reply('I am not a smart bot...');
            $bot->reply('All I know is that you said: '.$message);
        });

        $this->bot->listen();
    }
}

To test that, I installed the botman web widget following the instructions here. First step is to create a view that contains the code that will be loaded in an iframe by the widget. So here is my resources/views/chatbot/iframe.blade.php

<!doctype html>
<html>
<head>
    <title>BotMan Widget</title>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/botman-web-widget@0/build/assets/css/chat.min.css">
</head>
<body>
<script id="botmanWidget" src='https://cdn.jsdelivr.net/npm/botman-web-widget@0/build/js/chat.js'></script>
</body>
</html>

And here are the routes to load it and the controller method to return the view:

// routes/web.php
Route::get( '/botman/iframe', [App\Http\Controllers\Chatbot\BotManController::class,'loadIframe']);

// BotmanController.php
public function loadIframe()
{
    return view('chatbot.iframe');
}

Finally, I added the following code to the homepage:

<script>
    var botmanWidget = {
        frameEndpoint: '/botman/iframe',
    };
</script>
<script src='https://cdn.jsdelivr.net/npm/botman-web-widget@0/build/js/widget.js'></script>

Which gave me the following results:

It's a good start but:

So let's change that.

Making the bot smart(er)

My final goal with this bot is to allow users to create an alert with any criteria. The bot could be used to replace the create alert page. Once it's ready, I'll also be able to make this from our Facebook page just by installing the botman Facebook messenger driver.

So far, our bot listens to pre-defined message and gives a pre-defined answer. In order to add more complex logic, we'll use the Conversation class. I'm not going to show everything as it's very specific to Moovino, although you can ask me on twitter if you'd like to see more. Here is what the conversation file looks like after implementing the very first message only:

<?php

namespace App\Service\BotConversations;

use BotMan\BotMan\Messages\Conversations\Conversation;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Outgoing\Question;

class NewAlertConversation extends Conversation
{
    public function run()
    {
        $this->intro();
    }

    private function intro()
    {
        $button = Question::create('Hello! I\'m the Moovino bot. I was created to help you find your dream home. To do so,
        I need to understand what your are looking for. I need to ask you 5 very simple questions. Should we start?')
            ->fallback('I did not understand that')
            ->callbackId('create_database')
            ->addButton(Button::create('Let\'s find my dream home!')
                ->name('Yes')
                ->value('yes'))
            ->addButton(Button::create('No thanks')
                ->name('No')
                ->value('no'));

        $this->bot->ask($button,function (Answer $answer) {
            if ($answer->getText() == 'no') {
                $this->bot->reply('That\'s fine. Let me know if you change your mind. If you want to learn more about my
                Moovino and the team, you can visit: https://moovino.com/');
            }
        });
    }

    private function askLocation()
    {
        $this->bot->say('Great. We\'ll start with your dream location. At this time, Moovino can only help
        you to find a new home in London. What tube station would you like to live next to? (One tube station only, you can
        add some more after)');

    }

    // ... some more bot logic
}

And I changed the handle method of the controller used for the bot:

public function handle()
{
    $this->bot->hears('{message}', function ($bot, $message) {
        $bot->startConversation(new NewAlertConversation());
    });

    $this->bot->listen();
}

Using Facebook Messenger

We need this bot to be available to people sending a message to Moovino's facebook page. Luckily Botman plays very nicely with messaging platforms such as messenger. I followed the instructions on the botman website to setup Messenger. Creating the Facebook application and connecting it to the bot via webhooks can sometimes be complicated. I recommand you watch the videos made by Marcel on the subject if you are struggling.

Botman is awesome because I didn't have to change any of the bot code. Everything worked exactly the same within messenger, including buttons, images etc.

Conclusions

Creating a bot is very easy and straightforward with botman. It can be a bit challenging during the first minutes as you get used to the logic. The documentation is very focused on integrating a bot to a new Laravel application with Botman Studio. As Moovino wasn't not a new application, I was a bit lost at first, but the Chatbot Magazine article really helped me to get started. I've only used the web driver and the facebook driver, and I have to say that I was amazed by the way that the exact same codebase was powering bots on different platforms. I think that, as everything else I tried before that was created by Marcel or BeyondCode, Botman is an amazing package.

If you want to test the bot I created, just talk to us via the messenger plug-in on moovino.com.


If you're interested in my work, follow me on twitter: @JhumanJ.


Resources used