diff --git a/src/Discord/Message.php b/src/Discord/Message.php index 07b7aea..d5d3d02 100644 --- a/src/Discord/Message.php +++ b/src/Discord/Message.php @@ -5,17 +5,23 @@ use Discord\Builders\Components\ActionRow; use Discord\Builders\Components\Button; use Discord\Builders\MessageBuilder; +use Discord\Http\Exceptions\NoPermissionsException; use Discord\Parts\Channel\Channel; use Discord\Parts\Channel\Message as ChannelMessage; +use Discord\Parts\Channel\Webhook; use Discord\Parts\Interactions\Interaction; use Discord\Parts\User\User; +use Discord\Repository\Channel\WebhookRepository; use Exception; use Illuminate\Support\Carbon; use Illuminate\Support\Str; use Laracord\Laracord; use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; use Throwable; +use function React\Async\await; + class Message { /** @@ -128,6 +134,11 @@ class Message */ protected array $files = []; + /** + * The message webhook. + */ + protected string|bool $webhook = false; + /** * The default embed colors. */ @@ -154,8 +165,10 @@ public function __construct(?Laracord $bot) $this->bot = $bot ?: app('bot'); $this - ->authorName($this->bot->discord()->user->username) - ->authorIcon($this->bot->discord()->user->avatar) + ->username($username = $this->bot->discord()->username) + ->avatar($avatar = $this->bot->discord()->avatar) + ->authorName($username) + ->authorIcon($avatar) ->success(); } @@ -173,6 +186,8 @@ public static function make(?Laracord $bot): self public function build(): MessageBuilder { $message = MessageBuilder::new() + ->setUsername($this->username) + ->setAvatarUrl($this->avatarUrl) ->setTts($this->tts) ->setContent($this->body) ->setComponents($this->getComponents()); @@ -197,12 +212,16 @@ public function build(): MessageBuilder /** * Send the message. */ - public function send(mixed $destination = null): ?ExtendedPromiseInterface + public function send(mixed $destination = null): PromiseInterface|ExtendedPromiseInterface|null { if ($destination) { $this->channel($destination); } + if ($this->webhook) { + return $this->handleWebhook(); + } + return $this->getChannel()->sendMessage($this->build()); } @@ -236,6 +255,62 @@ public function sendTo(mixed $user): ?ExtendedPromiseInterface return $user->sendMessage($this->build()); } + /** + * Send the message as a webhook. + */ + protected function handleWebhook(): ?ExtendedPromiseInterface + { + try { + /** @var WebhookRepository $webhooks */ + $webhooks = await($this->getChannel()->webhooks->freshen()); + } catch (NoPermissionsException) { + $this->bot->console()->error("\nMissing permission to fetch channel webhooks."); + + return null; + } + + if (! $webhooks) { + $this->bot->console()->error('Failed to fetch channel webhooks.'); + + return null; + } + + if ($this->webhook === true) { + $webhook = $webhooks->find(fn (Webhook $webhook) => $webhook->name === $this->bot->discord()->username); + + if (! $webhook) { + return $webhooks->save(new Webhook($this->bot->discord(), [ + 'name' => $this->bot->discord()->username, + ]))->then( + fn (Webhook $webhook) => $webhook->execute($this->build()), + fn () => $this->bot->console()->error('Failed to create message webhook.') + ); + } + + return $webhook->execute($this->build()); + } + + $webhook = $this->getChannel()->webhooks->get('url', $this->webhook); + + if (! $webhook) { + $this->bot->console()->error("Could not find webhook {$this->webhook} on channel to send message."); + + return null; + } + + return $webhook->execute($this->build()); + } + + /** + * Send the message as a webhook. + */ + public function webhook(string|bool $value = true): self + { + $this->webhook = $value; + + return $this; + } + /** * Reply to a message or interaction. */ @@ -358,6 +433,14 @@ public function content(?string $content): self return $this; } + /** + * Set the message avatar. + */ + public function avatar(?string $avatarUrl): self + { + return $this->avatarUrl($avatarUrl); + } + /** * Set the message avatar URL. */ @@ -505,6 +588,16 @@ public function footerText(?string $footerText): self return $this; } + /** + * Set the message thumbnail URL. + */ + public function thumbnail(?string $thumbnailUrl): self + { + $this->thumbnailUrl = $thumbnailUrl; + + return $this; + } + /** * Set the message thumbnail URL. */ @@ -525,6 +618,16 @@ public function url(?string $url): self return $this; } + /** + * Set the message image URL. + */ + public function image(?string $imageUrl): self + { + $this->imageUrl = $imageUrl; + + return $this; + } + /** * Set the message image URL. */ @@ -583,6 +686,14 @@ public function authorIcon(?string $authorIcon): self return $this; } + /** + * Clear the message author. + */ + public function clearAuthor(): self + { + return $this->authorName('')->authorIcon(''); + } + /** * Set the message fields. */