nwilging/laravel-discord-bot

为 Laravel 提供强大的 Discord 消息集成

1.1.1 2023-04-18 21:36 UTC

README

为 Laravel 提供强大的 Discord 消息集成

Tests Coverage Latest Stable Version License Total Downloads

关于

此包提供了一个通知通道,用于向 Discord 发送消息,还包括一系列工具、服务和组件,帮助您构建丰富的文本消息以及处理 Discord 交互

安装

先决条件

  1. Laravel v8+
  2. PHP 7.4+
  3. libsodium

使用 Composer 安装

composer require nwilging/laravel-discord-bot

配置

  1. 访问 Discord 开发者门户 并创建一个新应用
  2. 复制应用 ID 和公钥
  3. 创建一个机器人用户
  4. 重置机器人用户令牌并复制它

填写您的 .env

DISCORD_API_BOT_TOKEN=<bot user token from above>
DISCORD_APPLICATION_ID=<application id from above>
DISCORD_PUBLIC_KEY=<public key from above>

附加配置(可选)

处理交互时,默认的响应行为是“延迟” - 即停止 Discord 应用窗口中的加载过程,并返回无回复或其他消息。如果您想将其更改为“加载” - 这将在您的应用发送后续消息之前显示加载消息 - 请将以下内容添加到您的 .env

DISCORD_COMPONENT_INTERACTION_DEFAULT_BEHAVIOR=load

通知通道使用

您的通知类必须实现接口 Nwilging\LaravelDiscordBot\Contracts\Notifications\DiscordNotificationContract,并包含 toDiscord(): array 方法。

使用纯文本消息的示例

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Nwilging\LaravelDiscordBot\Contracts\Notifications\DiscordNotificationContract;
use Nwilging\LaravelDiscordBot\Support\Builder\ComponentBuilder;
use Nwilging\LaravelDiscordBot\Support\Builder\EmbedBuilder;

class TestNotification extends Notification implements DiscordNotificationContract
{
    use Queueable;

    public function via($notifiable)
    {
        return ['discord'];
    }

    public function toDiscord($notifiable): array
    {
        return [
            'contentType' => 'plain',
            'channelId' => 'channel ID',
            'message' => 'message content',
        ];
    }
}

使用富文本消息的示例

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Nwilging\LaravelDiscordBot\Contracts\Notifications\DiscordNotificationContract;
use Nwilging\LaravelDiscordBot\Support\Builder\ComponentBuilder;
use Nwilging\LaravelDiscordBot\Support\Builder\EmbedBuilder;

class TestNotification extends Notification implements DiscordNotificationContract
{
    use Queueable;

    public function via($notifiable)
    {
        return ['discord'];
    }

    public function toDiscord($notifiable): array
    {
        $embedBuilder = new EmbedBuilder();
        $embedBuilder->addAuthor('Me!');

        $componentBuilder = new ComponentBuilder();
        $componentBuilder->addActionButton('My Button', 'customId');

        return [
            'contentType' => 'rich',
            'channelId' => 'channel id',
            'embeds' => $embedBuilder->getEmbeds(),
            'components' => [
                $componentBuilder->getActionRow(),
            ],
        ];
    }
}

如何获取 channelId

如何查找 Discord ID

在向 Discord API 发送消息时,您必须指定实际的消息通道 ID。这可以通过在 Discord 客户端应用中启用开发者工具来实现。

交互使用

如果您正在发送包含按钮、输入、菜单等组件的消息,Discord 将准备将这些组件的用户交互作为请求发送到指定的端点 - 实质上是一个 webhook - 与交互事件有效负载。

设置交互

首先设置一个控制器和/或路由,您计划将其用作交互的回调 URL。在此路由的控制器中,注入 Nwilging\LaravelDiscordBot\Contracts\Services\DiscordInteractionServiceInterface

您将在上述服务上调用 handleInteractionRequest 方法。示例

use Nwilging\LaravelDiscordBot\Contracts\Services\DiscordInteractionServiceContract;

class MyController extends Controller
{
    private $interactionService;

    public function __construct(DiscordInteractionServiceContract $interactionService)
    {
        $this->interactionService = $interactionService;
    }
    
    public function handleDiscordInteraction(Request $request)
    {
        $response = $this->interactionService->handleInteractionRequest($request);
        return response()->json($response->toArray(), $response->getStatus());
    }
}

这将通过您的应用转发来自 Discord 的交互请求。 您必须通过此交互服务转发请求: Discord 需要签名验证,该包在每次交互请求上自动执行此操作。尝试在此包之外处理请求是可能的,但并不推荐。

监听交互事件

当用户与您的消息中的组件(如按钮)交互时,此交互将被发送到您的应用。此包将处理该交互请求,并在新的消息组件交互有效负载到达时触发一个事件。

此事件是 Nwilging\LaravelDiscordBot\Events\MessageComponentInteractionEvent,它包含一个方法 getInteractionRequest,它将返回原始请求对象的 ParameterBag。您可以通过调用 ->all() 来获取交互有效负载的数组表示形式。

您的监听器应该实现ShouldQueue接口以防止长时间运行的同步进程超时Discord交互请求,并向用户显示错误信息。您可以使用同步监听器,但请注意,如果在处理过程中发生错误,用户可能会在Discord中看到“此交互失败”的错误消息。

扩展消息组件交互处理器

MessageComponentInteractionHandler不支持直接扩展其功能。但是,它支持您的应用程序覆盖在处理交互后发送给Discord的即时响应。

如果您想在交互发生时发送回复消息,或者想要特别修改消息组件交互的默认行为,这很有用。

MessageComponentInteractionHandler会检查您的应用程序中实现Nwilging\LaravelDiscordBot\Contracts\Listeners\MessageComponentInteractionEventListenerContract接口的任何监听器。要覆盖默认响应,您的监听器必须实现此接口。

use Illuminate\Contracts\Queue\ShouldQueue;
use Nwilging\LaravelDiscordBot\Events\MessageComponentInteractionEvent;
use Nwilging\LaravelDiscordBot\Contracts\Listeners\MessageComponentInteractionEventListenerContract;

class MessageComponentInteractionListener implements MessageComponentInteractionEventListenerContract, ShouldQueue
{
    public function replyContent(MessageComponentInteractionEvent $event): ?string
    {
        // return null; - to override and send no reply
        return 'my reply message';
    }
    
    public function behavior(MessageComponentInteractionEvent $event): int
    {
        // return static::LOAD_WHILE_HANDLING; // Shows a loading message/status while handling
        // return static::REPLY_TO_MESSAGE; // Replies to the interaction with replyContent(). Required if you want to reply to the interaction
        return static::DEFER_WHILE_HANDLING; // Shows no loading message/status while handling
    }

    public function handle(MessageComponentInteractionEvent $event): void
    {
        // Handle the event like a normal listener
    }
}

由于这是一个监听器,您确实需要实现handle方法。建议将此类功能与您计划用于处理实际消息组件交互事件的监听器结合起来。

应用程序命令

Discord应用程序命令是灵活的命令,您的机器人可以向用户提供并接收随后的交互。此软件包提供了创建、更新和删除命令以及处理命令交互的能力。

命令构建器

有三种类型的命令可供选择

  • 斜杠命令 - Nwilging\LaravelDiscordBot\Support\Commands\SlashCommand
  • 消息命令 - Nwilging\LaravelDiscordBot\Support\Commands\MessageCommand
  • 用户命令 - Nwilging\LaravelDiscordBot\Support\Commands\UserCommand

命令类型具有与之相关的不同选项。例如,斜杠命令可以指定“选项”,这些选项本质上就是“参数”。

命令的选项可以在Nwilging\LaravelDiscordBot\Support\Commands\Options中找到。

以下是一个创建SlashCommand的示例

use Nwilging\LaravelDiscordBot\Support\Commands\SlashCommand;
use Nwilging\LaravelDiscordBot\Support\Commands\Options\ChannelOption;

$command = new SlashCommand('my-command', 'Command description');

$option1 = new ChannelOption('option1', 'description'); // Will allow user to select a channel
$option2 = new StringOption('option2', 'free text'); // Allows text input

$command->option($option1);
$command->option($option2);

要在Discord上创建此命令,请使用Nwilging\LaravelDiscordBot\Services\DiscordApplicationCommandService

use Nwilging\LaravelDiscordBot\Support\Commands\SlashCommand;
use Nwilging\LaravelDiscordBot\Contracts\Services\DiscordApplicationCommandServiceContract;

/** @var DiscordApplicationCommandServiceContract $appCommandService */
$appCommandService = app(DiscordApplicationCommandServiceContract::class);

$command = new SlashCommand('my-command', 'Command description');

// Creates a "global command" - available to any server your bot is a member of
$result = $appCommandService->createGlobalCommand($command);

// Creates a "guild command" - available only to the specified server/guild ID
$result = $appCommandService->createGuildCommand('server id', $command);

要更新命令,您可以使用create方法或使用update方法。

由于命令在类型和范围内具有唯一名称,我们将针对新命令的POST请求视为更新。这意味着用已使用的名称为您的应用程序创建新命令将更新现有命令。

Discord文档

use Nwilging\LaravelDiscordBot\Support\Commands\SlashCommand;
use Nwilging\LaravelDiscordBot\Contracts\Services\DiscordApplicationCommandServiceContract;

/** @var DiscordApplicationCommandServiceContract $appCommandService */
$appCommandService = app(DiscordApplicationCommandServiceContract::class);

$command = new SlashCommand('my-command', 'Command description');

// First create the command
$created = $appCommandService->createGlobalCommand($command);

// Get the resulting ID
$id = $created['id'];

// Make a change to the command
$command->version('updated!');

// First method to update a command:
$updated = $appCommandService->createGlobalCommand($command);

// Second method to update a command:
$updated = $appCommandService->updateGlobalCommand($id, $command);

要删除命令,您只需要命令ID

use Nwilging\LaravelDiscordBot\Contracts\Services\DiscordApplicationCommandServiceContract;

/** @var DiscordApplicationCommandServiceContract $appCommandService */
$appCommandService = app(DiscordApplicationCommandServiceContract::class);

$commandId = 'commandId';
$serverId = 'serverId'; // Only necessary for deleting guild commands

// Delete global command
$appCommandService->deleteGlobalCommand($commandId);

// Delete guild command
$appCommandService->deleteGuildCommand($serverId, $commandId);;

监听命令交互

扩展应用程序命令处理程序几乎与消息交互监听器相同,请参阅扩展交互处理程序

您的监听器应该监听Nwilging\LaravelDiscordBot\Events\ApplicationCommandInteractionEvent

<?php
declare(strict_types=1);

namespace App\Listeners;

use Nwilging\LaravelDiscordBot\Contracts\Listeners\ApplicationCommandInteractionEventListenerContract;
use Nwilging\LaravelDiscordBot\Events\ApplicationCommandInteractionEvent;
use Illuminate\Contracts\Queue\ShouldQueue;

class TestCommandListener implements ShouldQueue, ApplicationCommandInteractionEventListenerContract
{
    public function replyContent(ApplicationCommandInteractionEvent $event): ?string
    {
        return 'loading';
    }

    public function behavior(ApplicationCommandInteractionEvent $event): int
    {
        return static::REPLY_TO_MESSAGE;
    }

    public function command(): ?string
    {
        return null;
    }

    public function handle(ApplicationCommandInteractionEvent $event): void
    {
        // handle the interaction
    }
}

事件本身具有一些辅助方法,可以快速从交互中获取常用数据

/** @var \Nwilging\LaravelDiscordBot\Events\ApplicationCommandInteractionEvent $event **/
$event->getApplicationId(); // The application ID
$event->getChannelId(); // The channel that the command was run in
$event->getCommandId(); // The command's unique ID
$event->getCommandName(); // The name of the command
$event->getCommandType(); // Returns the command type, an integer

命令类型存储在Nwilging\LaravelDiscordBot\Support\Command上的常量中

public const TYPE_CHAT_INPUT = 1;
public const TYPE_USER = 2;
public const TYPE_MESSAGE = 3;