PHPackages                             plytas/laravel-discord-interactions - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. plytas/laravel-discord-interactions

ActiveLibrary[API Development](/categories/api)

plytas/laravel-discord-interactions
===================================

Laravel (PHP) client that uses Discord HTTP API to create and respond to interactions

0.10(1mo ago)1404↑218.8%[4 PRs](https://github.com/Plytas/laravel-discord-interactions/pulls)MITPHPPHP ^8.2CI passing

Since Jun 14Pushed 5d ago1 watchersCompare

[ Source](https://github.com/Plytas/laravel-discord-interactions)[ Packagist](https://packagist.org/packages/plytas/laravel-discord-interactions)[ Docs](https://github.com/plytas/laravel-discord-interactions)[ GitHub Sponsors](https://github.com/Plytas)[ RSS](/packages/plytas-laravel-discord-interactions/feed)WikiDiscussions main Synced yesterday

READMEChangelog (10)Dependencies (28)Versions (28)Used By (0)

Laravel (PHP) client that uses Discord HTTP API to create and respond to interactions
=====================================================================================

[](#laravel-php-client-that-uses-discord-http-api-to-create-and-respond-to-interactions)

[![Latest Version on Packagist](https://camo.githubusercontent.com/b2b7869d1d96c46d363f29b0478326494b8dc3213cae463045035bdba6870671/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f706c797461732f6c61726176656c2d646973636f72642d696e746572616374696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/plytas/laravel-discord-interactions)[![GitHub Tests Action Status](https://camo.githubusercontent.com/f747d4bbbd9d66feab8235f7485e0a22d3371d6d904372057e481a432c8ab722/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f706c797461732f6c61726176656c2d646973636f72642d696e746572616374696f6e732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/plytas/laravel-discord-interactions/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/8d36bc9e1ac14261189afb566aa0e912c38a7dd6bc21ca35402840afd503ef12/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f706c797461732f6c61726176656c2d646973636f72642d696e746572616374696f6e732f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/plytas/laravel-discord-interactions/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/fdfef341bd3bee18f192e87310a62567969c8722043cf1f4e3ad29be787d6ee6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f706c797461732f6c61726176656c2d646973636f72642d696e746572616374696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/plytas/laravel-discord-interactions)

Create rich Discord interactions and respond to them using Laravel. Utilizes Discord HTTP webhooks without the need of a long-running process.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require plytas/laravel-discord-interactions
```

You can publish the config file with:

```
php artisan vendor:publish --tag="discord-interactions-config"
```

This is the contents of the published config file:

```
return [
    'application_id' => env('DISCORD_APPLICATION_ID'),
    'public_key' => env('DISCORD_PUBLIC_KEY'),
    'bot_token' => env('DISCORD_BOT_TOKEN'),

    'route' => [
        'path' => env('DISCORD_ROUTE', '/discord'),

        'middleware' => [
            'before' => [
                //ThrottleRequests::class,
            ],
            'after' => [

            ],
        ],
    ],
];
```

### Configuration

[](#configuration)

Create a new discord application at . Copy the application id and public key from "General information" tab and bot token from "Bot" tab to your `.env` file.

### Interactions endpoint setup

[](#interactions-endpoint-setup)

For local development you can use services such as [expose](https://expose.dev) or [ngrok](https://ngrok.com/) to expose your local server to the internet.

In your discord application fill in `Interactions Endpoint URL` under "General information" with the url of your server followed by the path you set in the config file. By default it is `/discord`.

```
https://your-server-url.com/discord

```

When clicking the "Save Changes" button, Discord will send a couple `POST` request to the provided URL to verify the endpoint. One of them will intentionally contain an invalid signature. The package will automatically respond to these requests appropriately.

If the changes are saved successfully, you are good to go!

Usage
-----

[](#usage)

### Creating a command

[](#creating-a-command)

To create a new chat command, create a new class that implements the `Plytas\Discord\Contracts\DiscordCommand` interface.

```
use Plytas\Discord\Contracts\DiscordCommand;
use Plytas\Discord\Data\DiscordInteraction;
use Plytas\Discord\Data\DiscordMessage;
use Plytas\Discord\Data\DiscordResponse;

class PingCommand implements DiscordCommand
{
    public function description(): string
    {
        return 'Replies with pong';
    }

    public function handle(DiscordInteraction $interaction): DiscordResponse
    {
        return $interaction->respondWithMessage(
            DiscordMessage::new()
                ->setContent('Pong!')
                ->ephemeral()
        );
    }
}
```

### Registering a command

[](#registering-a-command)

You can register commands using `Plytas\Discord\DiscordCommandRegistry::setCommands` method. This can be done in the `boot()` method of a service provider.

```
use Plytas\Discord\DiscordCommandRegistry;

DiscordCommandRegistry::setCommands([
    'ping' => PingCommand::class,

    // Nested commands
    'user' => [
        'role' => [
            'add' => AddRoleCommand::class,
            'remove' => RemoveRoleCommand::class,
        ],
    ],
]);
```

And finally call `php artisan discord:register-commands` to register the commands with Discord. It's recommended to run this command in a deployment script.

### Responding to interactions

[](#responding-to-interactions)

Your commands will receive a `DiscordInteraction` object that contains information about the interaction. You can respond to the interaction directly by returning a `DiscordResponse` object. `DidcordInteraction` object contains helper methods to create responses such as `respondWithMessage()`, `updateMessage()` and `showModal()`.

You must respond to interactions within **3** seconds. If you fail to do so, Discord will show a generic error message to the user. If you need more time to process the interaction, it is recommended to respond with a message that indicates that the command is still processing. After processing is done, you can use `\Plytas\Discord\Facades\Discord::updateInteractionMessage()` in a `\Illuminate\Support\Facades\App::terminating()` callback to update the message.

```
use Illuminate\Support\Facades\App;
use Plytas\Discord\Contracts\DiscordCommand;
use Plytas\Discord\Data\DiscordInteraction;
use Plytas\Discord\Data\DiscordMessage;
use Plytas\Discord\Data\DiscordResponse;
use Plytas\Discord\Facades\Discord;

class PingCommand implements DiscordCommand
{
    public function description(): string
    {
        return 'Replies with pong';
    }

    public function handle(DiscordInteraction $interaction): DiscordResponse
    {
        // Register a terminating callback to update the message after processing is done
        App::terminating(function () use ($interaction) {
            // Simulate a long-running process
            sleep(5);

            Discord::updateInteractionMessage(
                interaction: $interaction,
                message: DiscordMessage::new()
                    ->setContent('Pong!')
                    ->ephemeral()
            );
        });

        // Respond with a message that indicates that the command is still processing
        return $interaction->respondWithMessage(
            DiscordMessage::new()
                ->setContent('Calculating...')
                ->ephemeral() // Only the user who invoked the command can see the message
        );
    }
}
```

### Responding to component interactions

[](#responding-to-component-interactions)

You can add components to your messages to allow users to interact with them.

```
use Plytas\Discord\Components\ActionRow;
use Plytas\Discord\Components\Button;
use Plytas\Discord\Contracts\DiscordCommand;
use Plytas\Discord\Data\DiscordInteraction;
use Plytas\Discord\Data\DiscordMessage;
use Plytas\Discord\Data\DiscordResponse;
use Plytas\Discord\Enums\ButtonStyle;

class RockPaperScissorsCommand implements DiscordCommand
{
    public function description(): string
    {
        return 'Play rock-paper-scissors';
    }

    public function handle(DiscordInteraction $interaction): DiscordResponse
    {
        return $interaction->respondWithMessage(
            DiscordMessage::new()
                ->setContent('Select your move')
                ->addComponent(
                    component: ActionRow::new()
                        ->addComponent(
                            component: Button::new()
                                ->setCustomId('rock')
                                ->setLabel('Rock')
                                ->setEmoji('🪨')
                                ->setStyle(ButtonStyle::Primary)
                        )
                        ->addComponent(
                            component: Button::new()
                                ->setCustomId('paper')
                                ->setLabel('Paper')
                                ->setEmoji('📄')
                                ->setStyle(ButtonStyle::Primary)
                        )
                        ->addComponent(
                            component: Button::new()
                                ->setCustomId('scissors')
                                ->setLabel('Scissors')
                                ->setEmoji('✂️')
                                ->setStyle(ButtonStyle::Primary)
                        )
                )
                ->ephemeral() // Only the user who invoked the command can see the message
        );
    }
}
```

You can respond to component interactions by creating a new class that implements the `\Plytas\Discord\Contracts\DiscordComponentHandler` interface.

```
use Illuminate\Support\Arr;
use Plytas\Discord\Contracts\DiscordComponentHandler;
use Plytas\Discord\Data\DiscordInteraction;
use Plytas\Discord\Data\DiscordMessage;
use Plytas\Discord\Data\DiscordResponse;

class RockPaperScissorsComponentHandler implements DiscordComponentHandler
{
    public function handle(DiscordInteraction $interaction): DiscordResponse
    {
        $playerSelection = $interaction->getMessageComponent()->custom_id;
        $botSelection = Arr::random(['rock', 'paper', 'scissors']);

        if ($playerSelection === $botSelection) {
            $message = 'It\'s a tie!';
        }

        $winningMoves = [
            'rock' => 'scissors',
            'paper' => 'rock',
            'scissors' => 'paper',
        ];

        if ($winningMoves[$playerSelection] === $botSelection) {
            $message = 'You win!';
        } else {
            $message = 'You lose!';
        }

        return $interaction->updateMessage(
            DiscordMessage::new()
                ->setContent($message)
                ->ephemeral()
        );
    }
}
```

### Registering component handlers

[](#registering-component-handlers)

You can register component handlers using `Plytas\Discord\DiscordComponentRegistry::setComponentHandlers()` method. This method accepts an array of `component_id => DiscordComponentHandler class`. This can be done in the `boot()` method of a service provider.

```
use Plytas\Discord\DiscordComponentRegistry;

DiscordComponentRegistry::setComponentHandlers([
    'rock' => RockPaperScissorsComponentHandler::class,
    'paper' => RockPaperScissorsComponentHandler::class,
    'scissors' => RockPaperScissorsComponentHandler::class,
]);
```

If you need more control over the component handler registration process, you can use `Plytas\Discord\DiscordComponentRegistry::handleComponentsUsing()` method. This method accepts a closure that receives `Plytas\Discord\Data\DiscordInteraction` object and expects a `Plytas\Discord\Data\DiscordResponse` object to be returned.

Imagine that your components have a dynamic custom id that contains the name of the game. You can use the following code to handle the components:

```
use Illuminate\Support\Str;
use Plytas\Discord\Data\DiscordInteraction;
use Plytas\Discord\Events\ComponentHandlerRegistered;

DiscordComponentRegistry::handleComponentsUsing(function(DiscordInteraction $interaction)  {
    $gameName = Str::afterLast($interaction->getMessageComponent()->custom_id, ':');

    return match ($gameName) {
        'rock-paper-scissors' => (new RockPaperScissorsComponentHandler)->handle($interaction),
        'coin-flip' => (new CoinFlipComponentHandler)->handle($interaction),
        'default' => $interaction->updateMessage(
            DiscordMessage::new()
                ->setContent('Invalid game')
                ->ephemeral()
        );
    };
});
```

Warning

Not all components and API features are supported yet. This package started as a personal project and is still in development. If you need a specific feature, feel free to open an issue or a pull request.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Plytas](https://github.com/Plytas)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance95

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 72.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~70 days

Recently: every ~159 days

Total

11

Last Release

48d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/17316322?v=4)[Vytautas Smilingis](/maintainers/Plytas)[@Plytas](https://github.com/Plytas)

---

Top Contributors

[![Plytas](https://avatars.githubusercontent.com/u/17316322?v=4)](https://github.com/Plytas "Plytas (42 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (11 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (5 commits)")

---

Tags

laraveldiscordinteractionslaravel-discord-interactions

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/plytas-laravel-discord-interactions/health.svg)

```
[![Health](https://phpackages.com/badges/plytas-laravel-discord-interactions/health.svg)](https://phpackages.com/packages/plytas-laravel-discord-interactions)
```

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k11.2M101](/packages/dedoc-scramble)[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.8M47](/packages/spatie-laravel-pdf)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

816333.9k3](/packages/defstudio-telegraph)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.0k](/packages/simplestats-io-laravel-client)[danestves/laravel-polar

A package to easily integrate your Laravel application with Polar.sh

8120.4k](/packages/danestves-laravel-polar)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
