mateodioev/tg-handler

创建Telegram机器人更简单的库


README

安装

composer require mateodioev/tg-handler
use Mateodioev\TgHandler\Bot;

使用

创建新实例并添加您的命令

$bot = new Bot($botToken);

$bot->onEvent(YourCommandInstance);

$bot->byWebhook();
// or
$bot->longPolling($timeout); // No needs server with ssl

创建新的命令实例

所有文本命令都需要扩展 Mateodioev\TgHandler\Commands\MessageCommand 类,并在 handle 方法中放置逻辑。

use Mateodioev\TgHandler\Commands\MessageCommand;
use Mateodioev\Bots\Telegram\Api;
use Mateodioev\TgHandler\Context;

class MyCommand extends MessageCommand
{
    protected string $name = 'start';
    protected string $description = 'Start the bot';
    
    public function handle(Api $bot, Context $context){
         // TODO: Implement handle() method.
         $bot->sendMessage($context->getChatId(), 'Hello!!!');
    }
}

$bot->onEvent(MyCommand::get());

此命令与 /start any text here/start 一起工作。如果需要其他前缀(/, !),则可以使用 addPrefix 方法或 prefix 属性添加。

class MyCommand extends MessageCommand
{
    protected string $name = 'start';
    protected string $description = 'Start the bot';
    protected array $prefix = ['/', '!'];
    
    // Additionally you can add command aliases
    protected array $alias = ['help'];
    
    ...
}

// or
$myCommand = MyCommand::get();
$myCommand->setPrefixes(['/', '!']); // Set prefix, no need to set `$prefix` property

使用中间件

您可以将中间件添加到您的命令中。中间件是将在命令之前执行的闭包。所有中间件的结果都将作为数组传递给命令。

例如,您可以创建一个中间件来检查用户是否已授权,如果没有,则命令将不会执行。

class MyCommand extends MessageCommand
{
    protected string $name = 'start';
    protected string $description = 'Start the bot';
    protected array $middlewares = [
        'authUser'
    ];
    
    public function handle(Api $bot, Context $context, array $args = []){
        // $args[0] is the result of the middleware authUser
        // Your logic here
    }
}

// Your middleware function 
function authUser(Context $ctx, Api $bot) {
    $user = User::find($ctx->getUserId());
    if (!$user) {
        $bot->replyTo($ctx->getChatId(), 'You are not authorized', $ctx->getMessageId())
        throw new \Mateodioev\TgHandler\Commands\StopCommand(); // Stop command execution
    }
    return $user;
}

您可以使用 StopCommand 异常来停止命令执行

使用过滤器

现在您可以为您的事件设置自定义过滤器以进行验证,所有过滤器都需要扩展 Mateodioev\TgHandler\Filters\Filter 接口。

use Mateodioev\Bots\Telegram\Api;
use Mateodioev\TgHandler\Context;

[\Mateodioev\TgHandler\Filters\FilterFromUserId(996202950)];
class FilterCommand extends MessageCommand
{
    protected string $name = 'filter';
    
    public function handle(Api $bot, Context $context, array $args = [])
    {
    }
}

现在此命令仅对用户 ID 996202950 响应

使用多个过滤器

您可以使用 FilterCollection

use Mateodioev\TgHandler\Events\Types\MessageEvent;
use Mateodioev\TgHandler\Filters\{FilterCollection, FilterMessageChat, FilterMessageRegex};

#[FilterCollection(
    new FilterMessageChat(TestChat::CHAT_ID),
    new FilterMessageRegex('/.*(mt?proto).*/i')
)]
class TestChat extends MessageEvent {
    const CHAT_ID = 'Put your chat id here';
    public function execute(Api $bot, Context $context, array $args = []) {
        // your logic here
    }
}

或者可以使用这个语法

use Mateodioev\TgHandler\Events\Types\MessageEvent;
use Mateodioev\TgHandler\Filters\{FilterCollection, FilterMessageChat, FilterMessageRegex};

#[FilterMessageChat(TestChat::CHAT_ID), FilterMessageRegex('/.*(filters).*/i')]
class TestChat extends MessageEvent {
    const CHAT_ID = 'Put your chat id here';
    public function execute(Api $bot, Context $context, array $args = []) {
        // your logic here
    }
}

会话

要开始一个新的会话,您只需在 Mateodioev\TgHandler\Events\EventInterface 接口中返回一个 Mateodioev\TgHandler\Conversations\Conversations 实例即可。

会话

use Mateodioev\Bots\Telegram\Api;
use Mateodioev\TgHandler\Context;
use Mateodioev\TgHandler\Conversations\MessageConversation;

class MyConversation extends MessageConversation
{
    // This is optional, only for validate the user input message
    protected string $format = 'My name is {w:name}';
    public function execute(Api $bot, Context $context, array $args = [])
    {
        $bot->sendMessage(
            $context->getChatId(),
            'Nice to meet you ' . $this->param('name')
        );
    }
}

EventInterface 处理器 在此情况下,是一个 MessageCommand 实例。

use Mateodioev\Bots\Telegram\Api;
use Mateodioev\TgHandler\Commands\MessageCommand;
use Mateodioev\TgHandler\Context;

class Name extends MessageCommand
{
    protected string $name = 'name';

    public function handle(Api $bot, Context $context, array $args = [])
    {
        $bot->replyTo(
            $context->getChatId(),
            'Please give me your name:',
            $context->getMessageId(),
        );

        // Register next conversation handler
        return nameConversation::new($context->getChatId(), $context->getUserId());
    }
}

注册会话

$bot->onEvent(Name::get());

有关更多详细信息,请参阅 examples 文件夹

日志记录

基本用法

use Mateodioev\TgHandler\Log\{Logger, TerminalStream};

$log = new Logger(new TerminalStream); // Print logs in terminal
$bot->setLogger($log); // Save logger

流集合

use Mateodioev\TgHandler\Log\{BulkStream, Logger, TerminalStream, PhpNativeStream};

BulkStream::add(new TerminalStream); // print logs in terminal
BulkStream::add((new PhpNativeStream)->activate(__DIR__)); // save logs in .log file and catch php warnings

$bot->setLogger(new Logger(new BulkStream));

设置日志级别

use Mateodioev\TgHandler\Log\{Logger, TerminalStream};

$log = new Logger(new TerminalStream);

// disable all logs
$log->setLevel(Logger:ALL, false);
// Enable only critical, error and emergency messages
$log->setLevel(Logger::CRITICAL | Logger::ERROR | Logger::EMERGENCY);

$bot->setLogger($log);

使用

记录器可以从机器人或事件实例(MessageCommand、CallbackCommand 等)使用。

机器人

$bot->getLogger()->debug('This is a debug message');
// output: [Y-m-d H:i:s] [DEBUG] This is a debug message
$bot->getLogger()->info('This is a debug message with {paramName}', [
    'paramName' => 'context params'
]);
// output: [Y-m-d H:i:s] [INFO] This is a debug message with context params

事件实例

use Mateodioev\TgHandler\Commands\MessageCommand;
use Mateodioev\Bots\Telegram\Api;
use Mateodioev\TgHandler\Context;

class MyCommand extends MessageCommand
{
    protected string $name = 'start';
    protected string $description = 'Start the bot';
    
    public function handle(Api $bot, Context $context)
    {
         $this->logger()->debug('Loging inside event');
         $this->logger()->info('User {name} use the command {commandName}', [
            'name'        => $context->getUserName() ?? 'null',
            'commandName' => $this->name
         ]);
    }
}

// register the command
$bot->onEvent(MyCommand::get());

管理错误

您可以在 Events::execute 方法 或事件中间件中发生异常时注册异常处理器。

// Base exception
class UserException extends \Exception
{}

// Specific exception
final class UserNotRegistered extends UserException {}
final class UserBanned extends UserException {}

// This only manage UserBanned exception
$bot->setExceptionHandler(UserBanned::class, function (UserBanned $e, Bot $bot, Context $ctx) {
    $bot->getApi()->sendMessage($ctx->getChatId(), 'You are banned');
});

// This manage all UserException sub classes
$bot->setExceptionHandler(UserException::class, function (UserException $e, Bot $bot, Context $ctx) {
    $bot->getLogger()->warning('Ocurrs an user exception in chat id: ' . $ctx->getChatId());
});