Sending Laravel Notifications To Discord Channels & Users

Tags: laravel, discord, notifications, php
Published: 2022-01-26 03:44:28

## Introduction

Discord is a messaging platform that allows you to send messages to your friends, family and communities, it is a great alternative to the likes of slack with a less "enterprise" and more "community" focus.

In this tutorial, we will learn how to send notifications to Discord channels and Discord users using Laravel.

>
If you want to see some code, I have packaged the whole tutorial in this github repo:

{% github MikeyBeLike/laravel-discord-notifications no-readme %}

There are many uses cases for this, but the most common use case is to send notifications to a Discord channel or a user when something independent of a discord interaction occur. A few examples:

- a payment on your website/app occurs and you want to thank and notify the user who made the payment
- a user has a new message on your website/app and you want to notify them via discord
- a community related event occurs and you want to notify the users within your channel

## Prerequisites

- A Discord server + channel
- A Discord bot account
- Some experience with Laravel
- A modern Laravel application setup (will be using Laravel 8 in the examples below)

### Create a discord channel

First we should start by creating a new discord channel. In your existing discord server you can create a new channel, this should be a text channel.

You can do this by clicking the server name in the top left and then clicking the "Create a new channel" button in the sidebar.

![Create Discord Channel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vq08gf4zo4q11r5ysbe5.png)

Click the "Text Channel" radio button, give your channel a name, (you can keep it public or private up to you) and then click the "Create Channel" button.
![Create Discord Channel Step 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8lcfatfzv262kifhtnj.png)

### Create your discord application/bot

Now that you have your discord channel created, you need to create a bot account.
Head over to the [Discord Developer Portal](https://discord.com/developers/applications) and click the "New Application" button in the top right corner.

Enter the name of your application and click the "Create" button.

Then navigate to the "Bot" link in the left hand side navigation and click the "Bot" button.

Follow the steps listed to create your bot, feel free to update the bot name too.

![Create Discord Bot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dw0443vdireny9opjkcm.png)

Congrats you've now created your discord bot! 🎉

### Invite bot to your channel

Next thing to do is invite your bot to your server!

I won't go into too much detail on how to invite your bot to your channel as there are many guides online on how to do this, here's one that I used:

[Invite your bot to your server](https://discordjs.guide/preparations/adding-your-bot-to-servers.html#adding-your-bot-to-servers)

Once done you should now see the bot in your server and it should look something like this.

![Bot in server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thsiwfq8okc9z1lpbeba.png)

Awesome we have no created our discord bot and it now "lives" in our server!

### Your Laravel application

>
This tutorial expects you have some experience of setting up and working with a Laravel application. If you don't yet have experience learning Laravel, their [docs](https://laravel.com/docs/8.x) are a great way to start!

The examples below are using Laravel 8.
>

#### Create your Laravel controller

```bash
php artisan make:controller DiscordNotificationDemo
```

This creates a file with some minimal boilerplate controller code.

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DiscordNotificationDemo extends Controller
{
    //
}

```

Typically your controller would be called from an external web service/event/etc which would eventually trigger the notification to our discord channel, but for the sake of demo purposes this example would be triggered directly from the url.

#### Create a route for your controller.

Open up your `routes/web.php` file and add the following line:

```php
use App\Http\Controllers\DiscordNotificationDemo;

// ...

Route::get('discord-notification', [DiscordNotificationDemo::class, 'index']);
```

## Setting up notifications

Laravel has a fluent API for working with sending notifications across a variety of delivery channels. You can find more information on the [notifications docs](https://laravel.com/docs/8.x/notifications).

By default Laravel comes with channels for sending notifications via email, server-client broadcasts, SMS & Slack. But also with the ability to send notifications to other third party services such as Discord and more.

Since Discord is not a first party notification channel, we need to use a third party library to send notifications via Discord. Luckily for us there is a [github account](https://github.com/laravel-notification-channels) that hosts a few different third party Laravel notification channels. We'll be using this open source package: [https://github.com/laravel-notification-channels/discord](https://github.com/laravel-notification-channels/discord).

### Setup the package

We can now install the package using composer.

```bash
composer require laravel-notification-channels/discord
```

Open your `config/app.php` file and load the service provider:

```php
// config/app.php
'providers' => [
    // ...
    /*
     * Package Service Providers...
     */
    NotificationChannels\Discord\DiscordServiceProvider::class,
    // ...
],
```

#### Include your Discord bot API token

- Head back to the Discord Developer Portal and click the "Bot" link in the left hand side navigation.
- Copy the token value under the "Build-A-Bot" section.
  ![Copy bot token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tqes55uzdj0u3f7z94sd.png)
- Open your `.env` file and add this line - replacing `YOUR_TOKEN_VALUE` with the copied token value.

```
DISCORD_API_TOKEN=YOUR_TOKEN_VALUE
```

- Open your `config/services.php` file and add the following to the existing array:

```php
// ...
'discord' => [
    'token' => env('DISCORD_API_TOKEN'),
],
```

- The bot already exists in your server but Discord requires us to connect via websocket connection and identify atleast once before we can send requests to the API over HTTP. Running the following command will connect the bot to the server and identify it:

```bash
php artisan discord:setup
```

Hopefully that should have all run well and we can now proceed to setting up our Laravel notifications.

### Setup the notification channel

In this example we'll be creating a notification to simply alert a channel that a user has made a donation towards our site. Laravel allows us to create a notification class by simply running the following command:

```bash
php artisan make:notification NewDonation
```

This gives us a new notification class that we can use to send notifications to our discord channel.

```php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class NewDonation extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', url('/'))
                    ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}
```

I've edited the default class created to only send a notification to our discord channel.

```php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use NotificationChannels\Discord\DiscordChannel; // <-- Notice this line
use NotificationChannels\Discord\DiscordMessage; // <-- Notice this line

class NewDonation extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [DiscordChannel::class];
    }

    public function toDiscord($notifiable)
    {
        return DiscordMessage::create($this->getMessage());
    }

    private function getMessage() {
        return 'A new donation has been made!';
    }
}

```

### Setup the notifiable model

Ideally you should have tables and models setup that store information about the discord guild and also the channel ID you want to send the notification to.

> You can get a channel's ID right clicking the channel name and clicking "Copy ID".

Assuming you have already have a table setup to store information about the guild and channel ID you want to post notification messages to, you should make sure your Guild model has the `notifiable` trait. e.g

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;

class Guild extends Model
{
    use HasFactory, Notifiable;

    public function routeNotificationForDiscord()
    {
        return $this->message_channel_id;
    }
}
```

`$this->message_channel_id` here would refer to the column in your guilds table where the channel ID is stored.

## Sending the notification

Now that we have our notification class created and our notifiable model setup, we can send the notification to our discord channel through the guild model.

Going back to our `DiscordNotificationDemo` controller. We can modify it like so:

```php
<?php

namespace App\Http\Controllers;

use App\Models\Guild;
use App\Notifications\NewDonation;
use Illuminate\Http\Request;

class DiscordNotificationDemo extends Controller
{
    public function index()
    {
        $guild = Guild::findOrFail(1);
        $guild->notify(new NewDonation());
    }
}
```

Now go to your your laravel project root and follow the endpoint you defined [above](#create-a-route-for-your-controller) `/discord-notification` and you should see a message sent to your discord channel!
![Discord message sent](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b69d9cs5hqqodizmu4q6.png)

### Mentioning roles or user(s)

The example above sends a very basic notification to the channel. However, you can also send a notification which mentions a specific user or role if you know the user's ID or the role ID.

We'll modify our `NewDonation` notification class to mention a specific user or role:

```php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use NotificationChannels\Discord\DiscordChannel; // <-- Notice this line
use NotificationChannels\Discord\DiscordMessage; // <-- Notice this line

class NewDonation extends Notification
{
    use Queueable;

    public $discordUserId;
    public $discordRoleId;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($discordUserId, $discordRoleId)
    {
        $this->discordUserId = $discordUserId;
        $this->discordRoleId = $discordRoleId;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [DiscordChannel::class];
    }

    public function toDiscord($notifiable)
    {
        return DiscordMessage::create($this->getMessage());
    }

    private function getMessage()
    {
        return "A new donation has been made by <@$this->discordUserId>! cc: <@&$this->discordRoleId>";
    }
}

```

To quickly explain this, we've added a `$discordUserId` and `$discordRoleId` public property to our notification class and included them in our constructor so that we can dynamically specify the user/role we want to mention. We've used these properties in our `getMessage()` method to update our message. We'll use these properties to mention a specific user or role in our notification.

>
To mention a specific user the syntax is `<@DISCORD_USER_ID>` and to mention a role the syntax is `<@&DISCORD_ROLE_ID>`.
>

And then we need to update our controller to send the notification with the new params we added to our notification's class constructor:

```php
/// ...
$guild->notify(new NewDonation(DISCORD_USER_ID, DISCORD_ROLE_ID));
```

And then we can see the message sent to the discord channel!

![Discord message sent with mentions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m3totkqq6f534vj121lm.png)

As you can see the interaction is no different than a regular mention (highlighted in yellow) in discord.

## Sending the notification in a DM to a user.

Sending notifications to a user(s) is very similar to sending notifications to a channel as Discord considers a private conversation between multiple users to also be a "channel".

The main differences are:

- Instead of copying a channel ID, we have to "generate" a DM channel between the user and the bot.
- We also would need to make sure we are storing the user's Discord ID in a "discord user's" table.
- Ensure the Discord user model has the `notifiable` trait.
- We would need to add a `routeNotificationForDiscord()` method to the Discord user model.

### Generating a DM channel

To generate a DM channel between a user and the bot, we can use the `getPrivateChannel()` method on the Discord client. This is an action that we should most likely do when a user logs in to our Laravel application via discord and we have access to their Discord ID. We can then use this ID to generate a DM channel with the bot.

_Assuming we have the user's Discord ID in a variable `$userId` stored in a database._ We could do:

```php
use NotificationChannels\Discord\Discord;
use App\Models\DiscordUser;
// ...
$channelId = app(Discord::class)->getPrivateChannel($userId);

DiscordUser::update([
    'discord_user_id' => $userId,
    'discord_private_channel_id' => $channelId,
]);
```

Which will store the user's Discord ID and the generated DM channel ID in the `discord_user` table.

### Updating the user's model

Similar to the `Guild` model, we should update our `DiscordUser` model as so:

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;

class DiscordUser extends Authenticatable
{
    use HasFactory, SoftDeletes, Notifiable;

    protected $guarded = ['id'];

    public function routeNotificationForDiscord()
    {
        return $this->discord_private_channel_id;
    }
}
```

### Sliding into the DMs as a bot 😏

Now that we have our user model updated, we can send a notification to the user's DM channel.

Let's create a new notification class

```php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class SlideIntoDm extends Notification
{
    use Queueable;

    public $discordUserId;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($discordUserId)
    {
        $this->discordUserId = $discordUserId;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [DiscordChannel::class];
    }

    public function toDiscord($notifiable)
    {
        return DiscordMessage::create($this->getMessage());
    }

    private function getMessage()
    {
        return "Hey <@$this->discordUserId> 👋🏾 I'm a bot, sliding into your DMs 😏";
    }
}
```

Update our controller.

```php
use App\Notifications\SlideIntoDm;
use App\Models\DiscordUser;

// ...
public function slide_into_dm()
{
    $discordUser = DiscordUser::find(1);
    $discordUser->notify(new SlideIntoDm(DISCORD_USER_ID));
}
```

Add the route:

```php
/// ...
Route::get('slide-into-dm', [DiscordNotificationDemo::class, 'slide_into_dm']);
```

## Conclusion

We've learnt how to send Discord notifications to a channel, a user, or both using Laravel. The examples above are very straight forward for demo purposes. But ideally you should use notifications to react to events in your application and then send a message to the channel or user.

If you have any questions feel free to drop a comment here or even hit me up on my socials or even send me a message on Discord - MikeyBeLike#6718

I hope this helps!