Skip to content

Commit

Permalink
✨ Allow restricting a chat command to a specific guild (Fixes #70)
Browse files Browse the repository at this point in the history
  • Loading branch information
Log1x authored Jun 6, 2024
2 parents 160483e + ebb0999 commit d13e5ef
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 39 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Build functional, elegant bots harnessing the full power of [Laravel](https://la
- ⚡️ Out of the box support for databases, caching, and many other Laravel features thanks to [Laravel Zero](https://laravel-zero.com/).
- 🚀 Instantly generate working bot [commands](https://laracord.com/docs/commands) and [event listeners](https://laracord.com/docs/events) with 0 knowledge.
- 🧑‍💻 Automatic handling of registering/updating/unregistering application [slash commands](https://laracord.com/docs/slash-commands).
- 🚚 Easy to use [interaction routing](https://laracord.com/docs/interactions) for persistence on message buttons and actions.
- 👷 Generate asynchronous [services/tasks](https://laracord.com/docs/services) that run parallel to the bot.
- 🌎 Optional [HTTP Server](https://laracord.com/docs/http-server) with native Laravel routing and [Livewire support](https://laracord.com/docs/livewire).
- 🔧 Fully configurable and extendable.
Expand Down
16 changes: 16 additions & 0 deletions src/Commands/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laracord\Commands;

use Discord\Parts\Guild\Guild;
use Discord\Parts\User\User;
use Illuminate\Support\Str;
use Laracord\Laracord;
Expand Down Expand Up @@ -57,6 +58,13 @@ abstract class AbstractCommand
*/
protected $description;

/**
* The guild the command belongs to.
*
* @var string
*/
protected $guild;

/**
* Determines whether the command requires admin permissions.
*
Expand Down Expand Up @@ -227,6 +235,14 @@ public function getDescription()
return $this->description;
}

/**
* Retrieve the command guild.
*/
public function getGuild(): ?string
{
return $this->guild ?? null;
}

/**
* Retrieve the bot instance.
*
Expand Down
8 changes: 6 additions & 2 deletions src/Commands/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,18 @@ abstract class Command extends AbstractCommand implements CommandContract
*/
public function maybeHandle($message, $args)
{
if ($this->getGuild() && $message->guild_id !== $this->getGuild()) {
return;
}

$this->server = $message->channel->guild;

if (! $this->isAdminCommand()) {
$this->handle($message, $args);

return;
}

$this->server = $message->channel->guild;

if ($this->isAdminCommand() && ! $this->isAdmin($message->author)) {
return;
}
Expand Down
5 changes: 4 additions & 1 deletion src/Commands/HelpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ class HelpCommand extends Command
*/
public function handle($message, $args)
{
$commands = collect($this->bot()->getRegisteredCommands())->filter(fn ($command) => ! $command->isHidden());
$commands = collect($this->bot()->getRegisteredCommands())
->filter(fn ($command) => ! $command->isHidden())
->filter(fn ($command) => $command->getGuild() ? $message->guild_id === $command->getGuild() : true)
->sortBy('name');

$fields = [];

Expand Down
19 changes: 2 additions & 17 deletions src/Commands/SlashCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@

abstract class SlashCommand extends AbstractCommand implements SlashCommandContract
{
/**
* The guild the command belongs to.
*
* @var string
*/
protected $guild;

/**
* The permissions required to use the command.
*
Expand Down Expand Up @@ -91,6 +84,8 @@ abstract public function handle($interaction);
*/
public function maybeHandle($interaction)
{
$this->server = $interaction->guild;

if (! $this->isAdminCommand()) {
$this->parseOptions($interaction);

Expand All @@ -101,8 +96,6 @@ public function maybeHandle($interaction)
return;
}

$this->server = $interaction->guild;

if ($this->isAdminCommand() && ! $this->isAdmin($interaction->member->user)) {
return $interaction->respondWithMessage(
$this
Expand Down Expand Up @@ -192,14 +185,6 @@ public function getSignature()
return Str::start($this->getName(), '/');
}

/**
* Retrieve the slash command guild.
*/
public function getGuild(): ?string
{
return $this->guild ?? null;
}

/**
* Retrieve the slash command bitwise permission.
*/
Expand Down
6 changes: 4 additions & 2 deletions src/Discord/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -528,10 +528,12 @@ public function color(string $color): self
};

if (str_starts_with($color, '#')) {
$color = hexdec(substr($color, 1));
$color = hexdec(
Str::of($color)->replace('#', '')->limit(6, '')->toString()
);
}

$this->color = $color;
$this->color = (string) $color;

return $this;
}
Expand Down
10 changes: 7 additions & 3 deletions src/Events/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,25 @@ public static function getEvents(): array
}

$classes = collect(File::allFiles($source))
->mapWithKeys(fn ($file) => [Str::of($file->getFilename())->replace('.php', '')->__toString() => $file->getPathname()]);
->mapWithKeys(fn ($file) => [Str::of($file->getFilename())->replace('.php', '')->toString() => $file->getPathname()]);

return collect($events)->mapWithKeys(function ($path, $event) use ($classes) {
$class = Str::of($event)
->lower()
->replace('_', ' ')
->headline()
->replace(' ', '')
->__toString();
->toString();

if (! $classes->has($class)) {
return [];
}

$name = Str::of($event)->lower()->replace('_', ' ')->headline()->__toString();
$name = Str::of($event)
->lower()
->replace('_', ' ')
->headline()
->toString();

return [$event => [
'key' => $event,
Expand Down
72 changes: 58 additions & 14 deletions src/Laracord.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Laracord
/**
* The event loop.
*/
protected $loop;
protected ?LoopInterface $loop = null;

/**
* The application instance.
Expand Down Expand Up @@ -141,6 +141,13 @@ class Laracord
*/
protected $httpServer;

/**
* The logger instance.
*
* @var \Laracord\Logging\Logger
*/
protected $logger;

/**
* The registered bot commands.
*/
Expand Down Expand Up @@ -208,18 +215,10 @@ public function boot(): void
$this->afterBoot();

$this->getLoop()->addTimer(1, function () {
$status = collect([
'command' => count($this->registeredCommands),
'event' => count($this->registeredEvents),
'service' => count($this->registeredServices),
'routes' => count(Route::getRoutes()->getRoutes()),
])
->filter()
->map(function ($count, $type) {
$string = Str::plural($type, $count);

return "<fg=blue>{$count}</> {$string}";
})->implode(', ');
$status = $this
->getStatus()
->map(fn ($count, $type) => "<fg=blue>{$count}</> {$type}")
->implode(', ');

$status = Str::replaceLast(', ', ', and ', $status);

Expand Down Expand Up @@ -289,11 +288,13 @@ protected function handleStream(string $data): void
'restart' => $this->restart(),
'invite' => $this->showInvite(force: true),
'commands' => $this->showCommands(),
'status' => $this->showStatus(),
'?' => $this->console()->table(['<fg=blue>Command</>', '<fg=blue>Description</>'], [
['shutdown', 'Shutdown the bot.'],
['restart', 'Restart the bot.'],
['invite', 'Show the invite link.'],
['commands', 'Show the registered commands.'],
['status', 'Show the bot status.'],
]),
default => $this->console()->error("Unknown command: <fg=red>{$command}</>"),
};
Expand Down Expand Up @@ -757,6 +758,27 @@ public function showCommands(): self
return $this;
}

/**
* Print the bot status to console.
*/
public function showStatus(): self
{
$uptime = now()->createFromTimestamp(LARAVEL_START)->diffForHumans();

$status = $this->getStatus()
->prepend($this->discord()->users->count(), 'user')
->prepend($this->discord()->guilds->count(), 'guild')
->mapWithKeys(fn ($count, $type) => [Str::plural($type, $count) => $count])
->prepend($uptime, 'uptime')
->prepend("{$this->discord()->username} ({$this->discord()->id})", 'bot')
->map(fn ($count, $type) => Str::of($type)->title()->finish(": <fg=blue>{$count}</>")->toString());

$this->console()->line(' <options=bold>Status</>');
$this->console()->outputComponents()->bulletList($status->all());

return $this;
}

/**
* Show the invite link if the bot is not in any guilds.
*/
Expand Down Expand Up @@ -848,7 +870,7 @@ public function getOptions(): array

$defaultOptions = [
'intents' => $this->getIntents(),
'logger' => Logger::make($this->console),
'logger' => $this->getLogger(),
'loop' => $this->getLoop(),
];

Expand All @@ -858,6 +880,14 @@ public function getOptions(): array
];
}

/**
* Get the logger instance.
*/
public function getLogger(): Logger
{
return $this->logger ??= Logger::make($this->console);
}

/**
* Get the Discord admins.
*/
Expand Down Expand Up @@ -1101,6 +1131,20 @@ public function getApplication(): Application
return $this->app;
}

/**
* Retrieve the bot status collection.
*/
public function getStatus(): Collection
{
return collect([
'command' => count($this->registeredCommands),
'event' => count($this->registeredEvents),
'service' => count($this->registeredServices),
'interaction' => count($this->interactions),
'route' => count(Route::getRoutes()->getRoutes()),
])->filter()->mapWithKeys(fn ($count, $type) => [Str::plural($type, $count) => $count]);
}

/**
* Safely handle the provided callback.
*/
Expand Down

0 comments on commit d13e5ef

Please sign in to comment.