Last active
December 25, 2024 19:14
-
-
Save mikield/fe2fda55c3df1010cf003752682e6a10 to your computer and use it in GitHub Desktop.
Extend DiscordCommandClient with Pipelines
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Extentions; | |
use Discord\CommandClient\Command; | |
use Discord\Discord; | |
use Discord\DiscordCommandClient; | |
use Discord\Helpers\Collection; | |
use Discord\Helpers\RegisteredCommand; | |
use Discord\Parts\Embed\Embed; | |
use Discord\Parts\Interactions\Interaction; | |
use Illuminate\Contracts\Container\Container; | |
use Illuminate\Pipeline\Pipeline; | |
use Illuminate\Support\Arr; | |
use Illuminate\Support\Str; | |
use function Discord\contains; | |
class RoutedDiscordCommandClient extends DiscordCommandClient | |
{ | |
private array $middlewares; | |
private array $commandMiddlewares; | |
private ?Container $container; | |
private array $slashCommandsMiddlewares; | |
public function __construct(array $options = [], array $middlewares = [], array $commandMiddlewares = [], array $slashCommandsMiddlewares = [], Container $container = null) | |
{ | |
$this->commandClientOptions = $this->resolveCommandClientOptions($options); | |
$this->middlewares = $middlewares; | |
$this->slashCommandsMiddlewares = $slashCommandsMiddlewares; | |
$this->commandMiddlewares = $commandMiddlewares; | |
$this->container = $container; | |
$discordOptions = array_merge($this->commandClientOptions['discordOptions'], [ | |
'token' => $this->commandClientOptions['token'], | |
]); | |
Discord::__construct($discordOptions); | |
$this->on('init', function () { | |
$this->commandClientOptions['prefix'] = str_replace('@mention', (string)$this->user, $this->commandClientOptions['prefix']); | |
$this->commandClientOptions['name'] = str_replace('<UsernamePlaceholder>', $this->username, $this->commandClientOptions['name']); | |
foreach ($this->commandClientOptions['prefixes'] as $key => $prefix) { | |
if (contains($prefix, ['@mention'])) { | |
$this->commandClientOptions['prefixes'][] = str_replace('@mention', "<@{$this->user->id}>", $prefix); | |
$this->commandClientOptions['prefixes'][] = str_replace('@mention', "<@!{$this->user->id}>", $prefix); | |
unset($this->commandClientOptions['prefixes'][$key]); | |
} | |
} | |
$this->on('message', function ($message) { | |
if ($message->author->id == $this->id) { | |
return; | |
} | |
if ($withoutPrefix = $this->checkForPrefix($message->content)) { | |
$args = str_getcsv($withoutPrefix, ' '); | |
$command = array_shift($args); | |
if (null !== $command && $this->commandClientOptions['caseInsensitiveCommands']) { | |
$command = strtolower($command); | |
} | |
if (array_key_exists($command, $this->commands)) { | |
$command = $this->commands[$command]; | |
} elseif (array_key_exists($command, $this->aliases)) { | |
$command = $this->commands[$this->aliases[$command]]; | |
} else { | |
// Command doesn't exist. | |
return; | |
} | |
/** @var Command $command */ | |
$result = (new Pipeline($this->container)) | |
->send($message) | |
->through(array_merge( | |
$this->middlewares, | |
$this->commandMiddlewares[$command->command] ?? [] | |
)) | |
->via('handle') | |
->then(function ($message) use ($command, $args) { | |
return $command->handle($message, $args); | |
}); | |
if (is_string($result)) { | |
$message | |
->reply($result) | |
->then(null, $this->commandClientOptions['internalRejectedPromiseHandler']) | |
->done(); | |
} | |
} | |
}); | |
}); | |
if ($this->commandClientOptions['defaultHelpCommand']) { | |
$this->registerCommand('help', function ($message, $args) { | |
$prefix = str_replace((string)$this->user, '@' . $this->username, $this->commandClientOptions['prefix']); | |
$fullCommandString = implode(' ', $args); | |
if (count($args) > 0) { | |
$command = $this; | |
while (count($args) > 0) { | |
$commandString = array_shift($args); | |
$newCommand = $command->getCommand($commandString); | |
if (null === $newCommand) { | |
return "The command {$commandString} does not exist."; | |
} | |
$command = $newCommand; | |
} | |
$help = $command->getHelp($prefix); | |
if (empty($help)) { | |
return; | |
} | |
$embed = new Embed($this); | |
$embed->setAuthor($this->commandClientOptions['name'], $this->client->user->avatar) | |
->setTitle($prefix . $fullCommandString . '\'s Help') | |
->setDescription(!empty($help['longDescription']) ? $help['longDescription'] : $help['description']) | |
->setFooter($this->commandClientOptions['name']); | |
if (!empty($help['usage'])) { | |
$embed->addFieldValues('Usage', '``' . $help['usage'] . '``', true); | |
} | |
if (!empty($this->aliases)) { | |
$aliasesString = ''; | |
foreach ($this->aliases as $alias => $command) { | |
if ($command != $commandString) { | |
continue; | |
} | |
$aliasesString .= "{$alias}\r\n"; | |
} | |
if (!empty($aliasesString)) { | |
$embed->addFieldValues('Aliases', $aliasesString, true); | |
} | |
} | |
if (!empty($help['subCommandsHelp'])) { | |
foreach ($help['subCommandsHelp'] as $subCommandHelp) { | |
$embed->addFieldValues($subCommandHelp['command'], $subCommandHelp['description'], true); | |
} | |
} | |
$message->channel | |
->sendEmbed($embed) | |
->then(null, $this->commandClientOptions['internalRejectedPromiseHandler']) | |
->done(); | |
return; | |
} | |
$embed = new Embed($this); | |
$embed->setAuthor($this->commandClientOptions['name'], $this->client->avatar) | |
->setTitle($this->commandClientOptions['name']) | |
->setType(Embed::TYPE_RICH) | |
->setFooter($this->commandClientOptions['name']); | |
$commandsDescription = ''; | |
$embedfields = []; | |
foreach ($this->commands as $command) { | |
$help = $command->getHelp($prefix); | |
if (empty($help)) { | |
continue; | |
} | |
$embedfields[] = [ | |
'name' => $help['command'], | |
'value' => $help['description'], | |
'inline' => true, | |
]; | |
$commandsDescription .= "\n\n`" . $help['command'] . "`\n" . $help['description']; | |
foreach ($help['subCommandsHelp'] as $subCommandHelp) { | |
$embedfields[] = [ | |
'name' => $subCommandHelp['command'], | |
'value' => $subCommandHelp['description'], | |
'inline' => true, | |
]; | |
$commandsDescription .= "\n\n`" . $subCommandHelp['command'] . "`\n" . $subCommandHelp['description']; | |
} | |
} | |
// Use embed fields in case commands count is below limit | |
if (count($embedfields) <= 25) { | |
foreach ($embedfields as $field) { | |
$embed->addField($field); | |
} | |
$commandsDescription = ''; | |
} | |
$embed->setDescription(substr($this->commandClientOptions['description'] . $commandsDescription, 0, 2048)); | |
$message->channel | |
->sendEmbed($embed) | |
->then(null, $this->commandClientOptions['internalRejectedPromiseHandler']) | |
->done(); | |
}, [ | |
'description' => 'Provides a list of commands available.', | |
'usage' => '[command]', | |
]); | |
} | |
} | |
/** | |
* Add listener for incoming application command from interaction. | |
* | |
* @param string|array $name | |
* @param callable|null $callback | |
* @param callable|null $autocomplete_callback | |
* | |
* @return RegisteredCommand | |
* @throws \LogicException | |
* | |
*/ | |
public function listenCommand($name, ?callable $callback = null, ?callable $autocomplete_callback = null): RegisteredCommand | |
{ | |
$commandName = is_array($name) ? implode('.', $name) : $name; | |
return parent::listenCommand($name, function (Interaction $interaction, Collection $params) use ($callback, $name) { | |
return (new Pipeline($this->container)) | |
->send(new SlashCommandPipelineContext($interaction, $params)) | |
->through(array_merge( | |
$this->slashCommandsMiddlewares, | |
$this->commandMiddlewares[is_array($name) ? implode('.', $name) : $name] ?? [] | |
)) | |
->via('handle') | |
->then(function (SlashCommandPipelineContext $context) use ($callback) { | |
return $callback($context->interaction, $context->params); | |
}); | |
}, $autocomplete_callback); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment