parsidev/telegram-bot-dialog

Telegram Bot API PHP SDK 扩展,允许在机器人中实现对话框

dev-master 2020-03-18 12:32 UTC

This package is auto-updated.

Last update: 2024-09-18 22:27:02 UTC


README

为 Telegram Bot API PHP SDK 扩展,允许在机器人中实现对话框

此库允许为基于 Telegram Bot API - PHP SDK(https://github.com/irazasyed/telegram-bot-sdk)的 Telegram 机器人制作简单的对话框。

### 安装 您可以使用 Composer 轻松安装此包

composer require parsidev/telegram-bot-dialog

每个对话框都应该实现为扩展基本 Dialog 的类,如下面的示例所示

<?php
use BotDialogs\Dialog;

/**
 * Class HelloDialog
 */
class HelloDialog extends Dialog
{
    // Array with methods that contains logic of dialog steps.
    // The order in this array defines the sequence of execution.
    protected $steps = ['hello', 'fine', 'bye'];

    public function hello()
    {
        $this->telegram->sendMessage([
            'chat_id' => $this->getChat()->getId(),
            'text' => 'Hello! How are you?'
        ]);
    }

    public function bye()
    {
        $this->telegram->sendMessage([
            'chat_id' => $this->getChat()->getId(),
            'text' => 'Bye!'
        ]);
        $this->jump('hello');
    }

    public function fine()
    {
        $this->telegram->sendMessage([
            'chat_id' => $this->getChat()->getId(),
            'text' => 'I\'m OK :)'
        ]);
    }
}

要初始化新的对话框,您必须使用 Dialogs 类的实例添加新的对话框实现。执行第一个和下一个步骤时,必须使用 update 对象作为参数调用 Dialogs::proceed() 方法。也可以通过类型提示使用 Telegram 命令和 DI。

use Telegram\Bot\Commands\Command;
use BotDialogs\Dialogs;
use App\Dialogs\HelloDialog;

class HelloCommand extends Command
{
    /**
     * @var string Command name
     */
    protected $name = 'hello';
    protected $description = 'Just say "Hello" and ask few questions';

    /**
     * @param Dialogs $dialogs
     */
    public function __construct(Dialogs $dialogs)
    {
        $this->dialogs = $dialogs;
    }

    public function handle($arguments)
    {
        $this->dialogs->add(new HelloDialog($this->update));
    }
}

并且在 webhook 控制器中的代码

use Telegram\Bot\Api;
use BotDialogs\Dialogs;

// ...

public function __construct(Api $telegram, Dialogs $dialogs)
{
  $this->telegram = $telegram;
  $this->dialogs = $dialogs;
}
    
// ...
    
$update = $this->telegram->commandsHandler(true);

if (!$this->dialogs->exists($update)) {
  // Do something if there are no existing dialogs
} else {
  // Call the next step of the dialog
  $this->dialogs->proceed($update);
}

使用 Redis 存储对话框信息(也用于 Dialog::remember() 方法推送的数据)。

### 对话步骤的复杂定义 您可以为您的对话框步骤定义默认文本回答。为此,您必须将步骤定义为包含名称和响应字段的数组。

class HelloDialog extends Dialog
{
    protected $steps = [
        [
            'name' => 'hello',
            'response' => 'Hello my friend!'
        ],
        'fine',
        'bye'
    ];
    
    // ...
}

在这种情况下,如果您不需要在步骤处理程序内部执行任何逻辑,则可以不定义它。只需将响应放在步骤定义中即可。这对于欢迎消息、提示/建议消息等效果很好。如果您想使用 markdown 格式化响应,只需将 markdown 字段设置为 true

此外,您可以在步骤中通过定义 jumpend 字段来控制对话框的方向。jump 作为 jump() 方法,对话框跳转到特定的步骤。end 字段设置为 true,在当前步骤后结束对话框。

此外,您还可以使用步骤的 is_dich(是否为二分问题)选项。如果此选项设置为 true,则可以使用 Dialog 实例的 yesno 字段来检查用户答案。例如

class HelloDialog extends Dialog
{
    protected $steps = [
        [
            'name' => 'hello',
            'response' => 'Hello my friend! Are you OK?'
        ],
        [
            'name' => 'answer',
            'is_dich' => true
        ],
        'bye'
    ];
    
    public function answer()
    {
        if ($this->yes) {
            // Send message "I am fine, thank you!"
        } elseif ($this->no) {
            // Send message "No, I am got a sick :("
        }
    }
}

config/dialogs.php 中,您可以修改 yes/no 的别称。

在二分问题中,通常您只需要发送响应并跳转到另一个步骤。在这种情况下,您可以定义具有响应的步骤,并将它们的名称设置为二分步骤中 'yes'、'no' 或 'default' 键的值。例如

class HelloDialog extends Dialog
{
    protected $steps = [
        [
            'name' => 'hello',
            'response' => 'Hello my friend! Are you OK?'
        ],
        [
            'name' => 'answer',
            'is_dich' => true,
            'yes' => 'fine',
            'no' => 'sick',
            'default' => 'bye'
        ],
        [
            'name' => 'fine',
            'response' => 'I am fine, thank you!',
            'jump' => 'bye',
        ],
        [
            'name' => 'sick',
            'response' => 'No, I am got a sick :(',
        ],
        'bye'
    ];
}

### 在对话框中使用访问控制 您可以继承 AuthorizedDialog 类,并将 Telegram 用户名放入 $allowedUsers 属性中。之后,仅允许列表中的用户启动对话框。

### Dialog 类的可用方法

  • start() - 从第一个步骤开始对话框
  • proceed() - 将对话框推进到下一个步骤
  • end() - 结束对话框
  • jump($step) - 跳转到特定的步骤
  • remember($value) - 记住一些信息供下一个步骤使用(目前只支持“短”记忆,仅用于一个步骤)
  • isEnd() - 检查对话框是否结束

### Dialogs 类的可用方法

  • add(Dialog $dialog) - 添加新的对话框
  • get(Telegram\Bot\Objects\Update $update) - 返回现有对话框的对象
  • proceed(Telegram\Bot\Objects\Update $update) - 为现有对话框运行下一个步骤处理程序
  • exists(Telegram\Bot\Objects\Update $update) - 检查是否存在对话框

### 在单独的文件中配置步骤

您可以在单独的 yaml 或 php 文件中定义对话框配置。为此,在对话框配置文件中设置 scenarios,使用对话框类名作为键,配置文件的路径作为值,例如

'scenarios' => [
        HelloDialog::class => base_path('config/dialogs/hello.yml')
],

生产环境中存储在默认缓存实例中的文件配置。因此,您应该在部署脚本中添加 php artisan cache:clear

## 计划改进的内容

  • 重构使用 Dialogs::add() 中的名称而不是对象,并将其重命名为 start()
  • 添加 LUIS API 支持 (https://www.luis.ai/)
  • 长期记忆