与Laravel和BotMan建立电报机器人

介绍 ( Introduction )

Being a Scotch.io reader you definitely know that we have covered creating Bots before, we have quite few posts on Slack Bots, Twitter Bots and other related topics, here’s a list if you would like to check them out:

作为Scotch.io读者,您肯定知道我们之前已经介绍过创建Bot,关于Slack Bot,Twitter Bots和其他相关主题的文章很少,如果您想查看这些列表,请查看以下列表:

  • Building a Slack Bot with Node.js and Chuck Norris Super Powers

    使用Node.js和Chuck Norris Super Powers构建Slack Bot
  • Build A Tweet Bot With Python ― Scotch

    使用Python构建Swech的Tweet Bot
  • Building a Slack Bot with Modern Node.js Workflows

    使用现代Node.js工作流程构建Slack Bot
  • Creating a Slack bot using botmanio

    使用botmanio创建一个Slack机器人

But today, we have something different for you, today we will be creating a Telegram bot for dog lovers. Yes, you heard it right. A Telegram Bot for dog lovers using Dog API and this is what it looks like:

但是今天,我们为您提供了一些不同的东西,今天,我们将为爱狗者创建一个Telegram机器人。 是的,您没听错。 使用Dog API的爱狗爱好者专用的Telegram Bot,外观如下:

That got you excited? See you in the next chapter.

那让你兴奋吗? 下一章见。

安装Laravel和Botman ( Installing Laravel & Botman )

The first step we will be taking to create this amazing Bot is installing Laravel and Botman. But before doing that let’s first take a quick look at what Botman is and how it works:

我们将要创建这个令人惊奇的Bot的第一步是安装Laravel和Botman 。 但是在开始之前,让我们先快速看一下Botman是什么以及它如何工作:

博特曼是什么? (What is Botman?)

BotMan is a framework agnostic PHP library that is designed to simplify the task of developing innovative bots for multiple messaging platforms, including Slack, Telegram, Microsoft Bot Framework, Nexmo, HipChat, Facebook Messenger and WeChat.

BotMan是一个与框架无关PHP库,旨在简化为多个消息传递平台(包括Slack,Telegram,Microsoft Bot Framework,Nexmo,HipChat,Facebook Messenger和WeChat)开发创新型机器人的任务。

它是如何工作的? (How does it work?)

$botman->hears('Bot, What’s the best Web Development training website?', function (BotMan $bot) {
    $bot->reply('Scotch.io for sure. Give me a harder question!!');
});

安装Botman Studio (Installing Botman Studio)

Marcel Pociot, The guy behind Botman has already saved us some time by creating Botman Studio which is a ready to use and up to date Laravel application with Botman and other testing tools (we will cover them later in this post) included.

Marcel Pociot , Botman背后的家伙已经通过创建Botman Studio节省了我们一些时间,该Botman Studio可以立即使用,并且包含了Botman和其他测试工具(我们将在本文稍后介绍),将其Laravel应用程序更新为最新版本。

Go ahead and create a new project:

继续创建一个新项目:

composer create-project --prefer-dist botman/studio ilovedogs

Now that we have a fresh installation of Laravel and Botman let’s check if everything is working fine. Open your terminal and run this command:

现在我们已经有了Laravel和Botman的全新安装,让我们检查一切是否正常。 打开终端并运行以下命令:

php artisan botman:tinker

If you typed in “Hi” and the Bot replied with “Hello” then you are ready to go.

如果您键入“ Hi”,并且Bot回答“ Hello”,那么您就可以开始了。

创建命令 ( Creating Commands )

Our amazing Bot should be able to respond to different message types and this is a list of the features we will be implementing, but of course you can always add any additional commands you would love your Bot to listen to:

我们令人惊叹的Bot应该能够响应不同的消息类型,这是我们将要实现的功能的列表,但是您当然可以随时添加希望Bot收听的任何其他命令:

  • Send a random dog photo from all breeds.

    发送所有品种的随机狗照片。
  • Send a random dog photo by its breed.

    按犬种发送随机照片。
  • Send a random dog photo by a its breed and sub-breed.

    发送由其品种和子品种组成的随机狗照片。
  • Have a conversation and provide help.

    进行交谈并提供帮助。
  • Respond to unrecognised commands.

    响应无法识别的命令。

Let’s clear the routes/botman.php file and start from scratch.

让我们清除routes / botman.php文件,然后从头开始。

发送所有品种的随机狗照片 (Send a random dog photo from all breeds)

In order to receive a random dog photo from the Bot you must text it /random and this is how we tell it to respond to that exact command:

为了从Bot接收随机的狗照片,您必须将其发短信/random ,这就是我们告诉它响应确切命令的方式:

In your routes/botman.php file:

在您的routes/botman.php文件中:



use App\Conversations\StartConversation;

$botman = resolve('botman');

$botman->hears('/random', 'App\Http\Controllers\AllBreedsController@random');

Go ahead and create the controller:

继续创建控制器:

php artisan make:controller AllBreedsController

This is what it should look like:

它应该是这样的:



namespace App\Http\Controllers;

use App\Services\DogService;
use App\Http\Controllers\Controller;

class AllBreedsController extends Controller
{
    /**
     * Controller constructor
     * 
     * @return void
     */
    public function __construct()
    {
        $this->photos = new DogService;
    }

    /**
     * Return a random dog image from all breeds.
     *
     * @return void
     */
    public function random($bot)
    {
        // $this->photos->random() is basically the photo URL returned from the service.
        // $bot->reply is what we will use to send a message back to the user.
        $bot->reply($this->photos->random());
    }

}

We first created an instance of our DogService (app//services/DogService.php) which will be responsible for making API calls to our endpoints and fetching the image and his is what it looks like:

我们首先创建了DogService的实例(app // services / DogService.php),该实例将负责对端点进行API调用并获取图像,其外观如下所示:



namespace App\Services;

use Exception;
use GuzzleHttp\Client;

class DogService
{
    // The endpoint we will be getting a random image from.
    const RANDOM_ENDPOINT = 'https://dog.ceo/api/breeds/image/random';

    /**
     * Guzzle client.
     *
     * @var GuzzleHttp\Client
     */
    protected $client;

    /**
     * DogService constructor
     * 
     * @return void
     */
    public function __construct()
    {
        $this->client = new Client;
    }

    /**
     * Fetch and return a random image from all breeds.
     *
     * @return string
     */
    public function random()
    {
        try {
            // Decode the json response.
            $response = json_decode(
                // Make an API call an return the response body.
                $this->client->get(self::RANDOM_ENDPOINT)->getBody()
            );

            // Return the image URL.
            return $response->message;
        } catch (Exception $e) {
            // If anything goes wrong, we will be sending the user this error message.
            return 'An unexpected error occurred. Please try again later.';
        }
    }
}

按品种发送随机的狗照片: (Send a random dog photo by its breed:)

For this one, we will use the command /b {breed} and same as above, we open the routes/botman.php file and tell the Bot to listen for that command by adding this line:

对于这个,我们将使用命令/b {breed} ,与上面相同,我们打开routes/botman.php文件,并通过添加以下代码行来告诉Bot监听该命令:

$botman->hears('/b {breed}', 'App\Http\Controllers\AllBreedsController@byBreed');

We will be using the same controller we used before. Open AllBreedsController and add this method to it:

我们将使用之前使用的相同控制器。 打开AllBreedsController并将此方法添加到其中:

/**
 * Return a random dog image from a given breed.
 *
 * @return void
 */
public function byBreed($bot, $name)
{
    // Because we used a wildcard in the command definition, Botman will pass it to our method.
    // Again, we let the service class handle the API call and we reply with the result we get back.
    $bot->reply($this->photos->byBreed($name));
}

Let’s define the byBreed method in our service class by opening the DogService class and adding this method to it:

让我们通过打开DogService类并将其添加到服务类中来定义byBreed方法:

/**
 * Fetch and return a random image from a given breed.
 *
 * @param string $breed
 * @return string
 */
public function byBreed($breed)
{
    try {
        // We replace %s     in our endpoint with the given breed name.
        $endpoint = sprintf(self::BREED_ENDPOINT, $breed);

        $response = json_decode(
            $this->client->get($endpoint)->getBody()
        );

        return $response->message;
    } catch (Exception $e) {
        return "Sorry I couldn\"t get you any photos from $breed. Please try with a different breed.";
    }
}

And don’t forget to add the endpoint const used above to the same file:

并且不要忘记将上面使用的端点const添加到同一文件中:

// The endpoint we will hit to get a random image by a given breed name.
const BREED_ENDPOINT = 'https://dog.ceo/api/breed/%s/images/random';

通过其品种和子品种发送随机的狗照片: (Send a random dog photo by a its breed and sub-breed:)

For sub-breed photos, let’s use the command /s {breed}:{subBreed}

对于次品种照片,我们使用命令/s {breed}:{subBreed}

$botman->hears('/s {breed}:{subBreed}', 'App\Http\Controllers\SubBreedController@random');

Creating the controller:

创建控制器:

php artisan make:controller SubBreedController

And we’ll define the random method as shown bellow:

我们将定义如下所示的random方法:



namespace App\Conversations;

use App\Services\DogService;
use App\Http\Controllers\Controller;

class SubBreedController extends Controller
{
    /**
     * Controller constructor
     * 
     * @return void
     */
    public function __construct()
    {
        $this->photos = new DogService;
    }

    /**
     * Return a random dog image from all breeds.
     *
     * @return void
     */
    public function random($bot, $breed, $subBreed)
    {
        $bot->reply($this->photos->bySubBreed($breed, $subBreed));
    }
}

And we add the needed endpoint and method to our DogService class:

然后,将所需的端点和方法添加到DogService类中:

// The endpoint we will hit to get a random image by a given breed name and its sub-breed.
const SUB_BREED_ENDPOINT = 'https://dog.ceo/api/breed/%s/%s/images/random';
/**
 * Fetch and return a random image from a given breed and its sub-breed.
 *
 * @param string $breed
 * @param string $subBreed
 * @return string
 */
public function bySubBreed($breed, $subBreed)
{
    try {
        $endpoint = sprintf(self::SUB_BREED_ENDPOINT, $breed, $subBreed);

        $response = json_decode(
            $this->client->get($endpoint)->getBody()
        );

        return $response->message;
    } catch (Exception $e) {
        return "Sorry I couldn\"t get you any photos from $breed. Please try with a different breed.";
    }
}

进行对话并提供帮助: (Have a conversation and provide help:)

A conversation is what you’d normally be using when building your Bots and the docs describes it as:

对话是建立Bot时通常使用的对话,而文档将其描述为:

When it comes to chat bots, you probably don't want to simply react to single keywords, but instead, you might need to gather information from the user, using a conversation. Let's say, that you want your chat bot to provide an elegant user onboarding experience for your application users.

当涉及到聊天机器人时,您可能不想简单地对单个关键字做出React,而是可能需要使用对话从用户那里收集信息。 假设您希望聊天机器人为您的应用程序用户提供优雅的用户入门体验。

Let’s create our conversation by adding this line to our routes/botman.php file:

让我们通过routes/botman.php添加到routes/botman.php文件来创建对话:

$botman->hears('Start conversation', 'App\Http\Controllers\ConversationController@index');

Generate the controller:

生成控制器:

php artisan make:controller ConversationController

And define an index method inside that class:

并在该类中定义一个索引方法:



namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Conversations\DefaultConversation;

class ConversationController extends Controller
{
    /**
     * Create a new conversation.
     *
     * @return void
     */
    public function index($bot)
    {
        // We use the startConversation method provided by botman to start a new conversation and pass
        // our conversation class as a param to it. 
        $bot->startConversation(new DefaultConversation);
    }
}

If you are using Botman Studio you should already have a Conversations folder inside the App folder, so go ahead and create a new class inside that folder and let’s name it DefaultConversation.php:

如果您使用的是Botman Studio,则应该在App文件夹中已经有一个Conversations文件夹,所以继续在该文件夹中创建一个新类,并将其命名为DefaultConversation.php



namespace App\Conversations;

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

class DefaultConversation extends Conversation
{
    /**
     * First question to start the conversation.
     *
     * @return void
     */
    public function defaultQuestion()
    {
        // We first create our question and set the options and their values.
        $question = Question::create('Huh - you woke me up. What do you need?')
            ->addButtons([
                Button::create('Random dog photo')->value('random'),
                Button::create('A photo by breed')->value('breed'),
                Button::create('A photo by sub-breed')->value('sub-breed'),
            ]);

        // We ask our user the question.
        return $this->ask($question, function (Answer $answer) {
            // Did the user click on an option or entered a text?
            if ($answer->isInteractiveMessageReply()) {
                // We compare the answer to our pre-defined ones and respond accordingly.
                switch ($answer->getValue()) {
                case 'random':
                    $this->say((new App\Services\DogService)->random());
                    break;
                    case 'breed':
                        $this->askForBreedName();
                        break;
                    case 'sub-breed':
                        $this->askForSubBreed();
                        break;
                }
            }
        });
    }

    /**
     * Ask for the breed name and send the image.
     *
     * @return void
     */
    public function askForBreedName()
    {
        $this->ask('What\'s the breed name?', function (Answer $answer) {
            $name = $answer->getText();

            $this->say((new App\Services\DogService)->byBreed($name));
        });
    }

    /**
     * Ask for the breed name and send the image.
     *
     * @return void
     */
    public function askForSubBreed()
    {
        $this->ask('What\'s the breed and sub-breed names? ex:hound:afghan', function (Answer $answer) {
            $answer = explode(':', $answer->getText());

            $this->say((new App\Services\DogService)->bySubBreed($answer[0], $answer[1]));
        });
    }

    /**
     * Start the conversation
     *
     * @return void
     */
    public function run()
    {
        // This is the boot method, it's what will be excuted first.
        $this->defaultQuestion();
    }
}

响应无法识别的命令: (Respond to unrecognised commands:)

Finally, we need to let the user know when they send a message our Bot does not recognise and we can do that by using the fallback method. Open your routes/botman.php and this line:

最后,我们需要在用户发送Bot无法识别的消息时让用户知道,我们可以使用后备方法来做到这一点。 打开您的routes/botman.php和以下行:

$botman->fallback('App\Http\Controllers\FallbackController@index');

Create the controller:

创建控制器:

php artisan make:controller FallbackController

And we simply return the message we want the user to see:

我们只是返回希望用户看到的消息:



namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class FallbackController extends Controller
{
    /**
     * Respond with a generic message.
     *
     * @param Botman $bot
     * @return void
     */
    public function index($bot)
    {
        $bot->reply('Sorry, I did not understand these commands. Try: \'Start Conversation\'');
    }
}

测试机器人 ( Testing The Bot )

  • Send a random dog photo from all breeds:

    发送所有品种的随机狗照片:

与Laravel和BotMan建立电报机器人_第1张图片

  • Send a random dog photo by its breed:

    按品种发送随机的狗照片:

与Laravel和BotMan建立电报机器人_第2张图片

  • Send a random dog photo by a its breed and sub-breed:

    通过其品种和子品种发送随机的狗照片:

与Laravel和BotMan建立电报机器人_第3张图片

  • Have a conversation and provide help:

    进行对话并提供帮助:

  • Respond to unrecognised commands:

    响应无法识别的命令:

与Laravel和BotMan建立电报机器人_第4张图片

安装电报驱动程序 ( Installing Telegram Driver )

After successfully creating and testing our commands it’s now time to integrate it with Telegram. To do that we will need to pull the Telegram driver provided by Botman:

成功创建和测试我们的命令后,现在是将其与Telegram集成的时候了。 为此,我们需要提取Botman提供的Telegram驱动程序:

composer require botman/driver-telegram

创建电报机器人 ( Creating a Telegram Bot )

We successfully created our Bot, defined the commands and tested it out now it’s time to create a Telegram Bot. Open the app and search for BotFather, type /newbot, enter the name the username for your bot and you are good to go.

我们现在成功创建了Bot,定义了命令并进行了测试,现在是时候创建Telegram Bot了。 打开应用程序并搜索BotFather ,输入/ newbot ,输入名称bot的用户名即可。

Add this to your .env file and replace YOUR_TOKEN with the token Telegram gave you:

将此添加到您的.env文件,并用令牌Telegram为您提供的令牌替换YOUR_TOKEN

TELEGRAM_TOKEN=YOUR_TOKEN

安装并运行ngrok ( Installing and running ngrok )

Because Telegram requires a valid and secure URL to set up webhooks (which we will get to in the next chapter) and receive messages from your users we will be using ngrok or you can deploy your app on a server and set up an SSL certificate, but to for the demo we will stick to ngrok. Bowse to their Download Page and click the download button that matches your operating system.

由于Telegram需要一个有效且安全的URL来设置webhooks(我们将在下一章中介绍)并接收来自用户的消息,因此我们将使用ngrok,或者您可以将应用程序部署在服务器上并设置SSL证书,但是对于演示,我们将坚持使用ngrok。 鞠躬进入他们的下载页面 ,然后单击与您的操作系统匹配的下载按钮。

Now cd into your app folder and run php artisan serve

现在cd到您的应用程序文件夹,运行php artisan serve

Time to run ngrok, cd into the folder where ngrok is and run ./ngrok http 8000

是时候运行ngrok,将cd插入ngrok所在的文件夹并运行./ngrok http 8000

The final step is linking our app to the Telegram Bot we created earlier and to do that we will make a POST request to this URL and pass the URL ngrok generated for us:

最后一步是将我们的应用程序链接到我们之前创建的Telegram Bot,为此,我们将向该URL发出POST请求,并传递为我们生成的URL ngrok:

https://api.telegram.org/bot{TOKEN}/setWebhook

You can do this with Postman or CURL by running this command:

您可以通过运行以下命令使用Postman或CURL进行此操作:

curl -X POST -F 'url=https://{YOU_URL}/botman' https://api.telegram.org/bot{TOKEN}/setWebhook

If you did that correctly you should receive this exact JSON response:

如果您正确地做到了这一点,那么您应该会收到以下确切的JSON响应:

{
    "ok": true,
    "result": true,
    "description": "Webhook was set"
}

在电报上测试 ( Test it out on Telegram )

  • Send a random dog photo from all breeds:

    发送所有品种的随机狗照片:

  • Send a random dog photo by its breed:

    按品种发送随机的狗照片:

  • Send a random dog photo by a its breed and sub-breed:

    通过其品种和子品种发送随机的狗照片:

  • Have a conversation and provide help:

    进行对话并提供帮助:

  • Respond to unrecognised commands:

    响应无法识别的命令:

最后的话 ( Final word )

I hope you found this tutorial useful, if you are following along and you created your own Bot feel free to share it either in the comments bellow or on twitter: Rachid Laasri

我希望您发现本教程对您有所帮助,如果您继续进行,并且创建了自己的Bot,可以在下面的评论中或在Twitter上分享它: Rachid Laasri

See you soon with another tutorial!

下次再见!

翻译自: https://scotch.io/tutorials/build-a-telegram-bot-with-laravel-and-botman

你可能感兴趣的:(python,java,php,大数据,人工智能)