Laracord's HTTP server while implementing Laravel's routing also brings in the necessary requirements for Livewire.
While Laracord has not been thoroughly tested with everything Livewire has to offer, it has been tested with basic full page components and can be a very quick and powerful way to create a basic web interface to interact with your bot instance in real-time without Javascript.
Note
While this provides a great way to easily manage a personal bot, it is strongly discouraged to use the Laracord HTTP server to host any kind of user-facing application.
In this example, we will install Livewire and create a simple message component that is capable of showing every user visible to the bot in a select dropdown and firing off a message using the bot instance when clicking send.
Start by installing Livewire using Composer:
$ composer require livewire/livewire
Once installed, you will need to generate an application key (APP_KEY
). This can be done using the laracord
binary:
$ php laracord key:generate
The final step is to add the Livewire service provider to providers
in config/app.php
:
'providers' => [
App\Providers\BotServiceProvider::class,
Livewire\LivewireServiceProvider::class,
],
Before creating a component, you will need to create an app.blade.php
layout for Livewire to use. You can create this using livewire:layout
:
$ php laracord livewire:layout
Once app.blade.php
has been created, you will need to add the @livewireStyles
and @livewireScripts
Blade directives to the layout.
Here is a full example including Tailwind's CDN since Laracord does not include frontend tooling out of the box:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $title ?? 'Laracord' }}</title>
<script src="https://cdn.tailwindcss.com"></script>
@livewireStyles
</head>
<body>
{{ $slot }}
@livewireScripts
</body>
</html>
For this example, we will create a simple full page component. We can start by using the make:livewire
console command:
$ php laracord make:livewire Message
After the component is created, we can create a route for it in app/Bot.php
:
<?php
namespace App;
use App\Livewire\Message;
use Illuminate\Support\Facades\Route;
use Laracord\Laracord;
class Bot extends Laracord
{
/**
* The HTTP routes.
*/
public function routes(): void
{
Route::middleware('auth')->group(function () {
Route::get('/message', Message::class);
});
}
}
Note
It is strongly recommended to put routes behind the auth middleware if the bot is publicly accessible. See HTTP Server Security to learn more.
Once our route is configured, we can switch over to the message component that was generated by make:livewire
located in app/Livewire/Message.php
and add in the logic:
<?php
namespace App\Livewire;
use Laracord\HasLaracord;
use Livewire\Attributes\Locked;
use Livewire\Component;
class Message extends Component
{
use HasLaracord;
/**
* The selected user.
*
* @var string
*/
public $user;
/**
* The message to send.
*
* @var string
*/
public $message;
/**
* The Discord users.
*
* @var array
*/
#[Locked]
public $members;
/**
* Render the component.
*
* @return \Illuminate\View\View
*/
public function render()
{
$this->members = collect($this->discord()->users->map(fn ($user) => [
'id' => $user->id,
'username' => $user->username,
]))->keyBy('id');
return view('livewire.message');
}
/**
* Send a message to the selected user.
*
* @return void
*/
public function sendMessage()
{
$this->validate([
'user' => 'required',
'message' => 'required|min:3|max:150',
]);
if (! $this->members->has($this->user)) {
$this->addError('user', 'The selected user does not exist.');
return;
}
$this
->message($this->message)
->sendTo($this->user);
$this->reset('message');
session()->flash('success', 'The message has been sent.');
}
}
Note
Thanks to the
WithLaracord
trait, the methods we are used to using when writing commands are available in the Livewire component such as bot(), discord(), console(), and message().
Let's break down the above component. To start, we create our properties:
In the render()
method, we set our members
property by mapping the Discord users by id
and username
and then keying them by id
. Keying them by id
will be convenient for validation.
In the sendMessage()
method, we start by using basic Laravel validation to check that the user
and message
are filled out and the message
meets a generic minimum/maximum length.
Once validate()
passes, we do our own quick validation to ensure that the user attempting to be messaged is in the users list and hasn't been tampered with.
Once validation is complete, we can send the message using the message()
method similar to how we would in a command, reset the message
textarea, and flash a success
message.
The component view is located in resources/views/livewire/message.blade.php
and will be composed of a simple select dropdown, a textarea, and a send message button. I won't go into specifics for this one:
<div class="max-w-2xl p-8 mx-auto">
<h1 class="mb-6 text-3xl">Send a Message</h1>
<div class="grid gap-8">
<div>
<select wire:model="user" class="w-full px-3 py-2 border">
<option value="">Select a member...</option>
@foreach ($members as $member)
<option value="{{ $member['id'] }}">{{ $member['username'] }}</option>
@endforeach
</select>
@error('user')
<div class="mt-1 text-red-500">{{ $message }}</div>
@enderror
</div>
<div>
<textarea
class="w-full px-3 py-2 border"
wire:model="message"
rows="5"
placeholder="Enter a message..."
></textarea>
@error('message')
<div class="mt-1 text-red-500">{{ $message }}</div>
@enderror
</div>
<button class="px-4 py-2 text-white bg-blue-500" wire:click="sendMessage">
Send Message
</button>
@session('success')
<div class="px-4 py-3 text-green-700 bg-green-100 rounded">
<b>Success</b>
<p>{{ session('success') }}</p>
</div>
@endsession
</div>
</div>
Once your component is created, it should be ready and accessible at localhost:8080/messages
by default once booting your bot.