crownrp/laravel-discord-bot

为Laravel提供强大的Discord消息集成,支持添加角色

v1.0.8 2023-05-18 10:21 UTC

This package is auto-updated.

Last update: 2024-09-18 13:30:05 UTC


README

为Laravel扩展的强大的Discord消息集成,增加了管理公会角色的功能

关于

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

安装

先决条件

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

使用Composer安装

composer require crownrp/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应用程序命令是灵活的命令,您的机器人可以向用户提供,并接收后续的交互。此包提供了创建、更新和删除命令以及处理命令交互的能力。

命令构建器

有三种类型的命令可用

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

命令类型具有与之关联的不同选项。例如,slash命令可以指定“选项”,这实际上是“参数”。

命令的选项可以在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;