diff --git a/src/Discord/Parts/Channel/Channel.php b/src/Discord/Parts/Channel/Channel.php index e124770b8..6c911c052 100644 --- a/src/Discord/Parts/Channel/Channel.php +++ b/src/Discord/Parts/Channel/Channel.php @@ -35,6 +35,7 @@ use Discord\Repository\Channel\ThreadRepository; use InvalidArgumentException; use React\Promise\ExtendedPromiseInterface; +use RuntimeException; use Symfony\Component\OptionsResolver\OptionsResolver; use Traversable; @@ -692,20 +693,37 @@ protected function setPermissionOverwritesAttribute(array $overwrites): void */ public function startThread(string $name, bool $private = false, int $auto_archive_duration = 1440): ExtendedPromiseInterface { + if ($private && ! $this->guild->feature_private_threads) { + return reject(new RuntimeException('Guild does not have access to private threads.')); + } + if ($this->type == Channel::TYPE_NEWS) { if ($private) { - throw new InvalidArgumentException('You cannot start a private thread within a news channel.'); + return reject(new InvalidArgumentException('You cannot start a private thread within a news channel.')); } $type = Channel::TYPE_NEWS_THREAD; } elseif ($this->type == Channel::TYPE_TEXT) { $type = $private ? Channel::TYPE_PRIVATE_THREAD : Channel::TYPE_PUBLIC_THREAD; } else { - throw new InvalidArgumentException('You cannot start a thread in this type of channel.'); + return reject(new InvalidArgumentException('You cannot start a thread in this type of channel.')); } if (! in_array($auto_archive_duration, [60, 1440, 4320, 10080])) { - throw new InvalidArgumentException('`auto_archive_duration` must be one of 60, 1440, 4320, 10080.'); + return reject(new InvalidArgumentException('`auto_archive_duration` must be one of 60, 1440, 4320, 10080.')); + } + + switch ($auto_archive_duration) { + case 4320: + if (! $this->guild->feature_three_day_thread_archive) { + return reject(new RuntimeException('Guild does not have access to three day thread archive.')); + } + break; + case 10080: + if (! $this->guild->feature_seven_day_thread_archive) { + return reject(new RuntimeException('Guild does not have access to seven day thread archive.')); + } + break; } return $this->http->post(Endpoint::bind(Endpoint::CHANNEL_THREADS, $this->id), [ diff --git a/src/Discord/Parts/Channel/Message.php b/src/Discord/Parts/Channel/Message.php index 9d63ccb13..2c3e88a29 100644 --- a/src/Discord/Parts/Channel/Message.php +++ b/src/Discord/Parts/Channel/Message.php @@ -29,6 +29,9 @@ use Discord\Repository\Channel\ReactionRepository; use InvalidArgumentException; use React\Promise\ExtendedPromiseInterface; +use RuntimeException; + +use function React\Promise\reject; /** * A message which is posted to a Discord text channel. @@ -500,8 +503,25 @@ public function getLinkAttribute(): ?string */ public function startThread(string $name, int $auto_archive_duration = 1440): ExtendedPromiseInterface { + if (! $this->guild) { + return reject(new RuntimeException('You can only start threads on guild text channels.')); + } + if (! in_array($auto_archive_duration, [60, 1440, 4320, 10080])) { - throw new InvalidArgumentException('`auto_archive_duration` must be one of 60, 1440, 4320, 10080.'); + return reject(new InvalidArgumentException('`auto_archive_duration` must be one of 60, 1440, 4320, 10080.')); + } + + switch ($auto_archive_duration) { + case 4320: + if (! $this->guild->feature_three_day_thread_archive) { + return reject(new RuntimeException('Guild does not have access to three day thread archive.')); + } + break; + case 10080: + if (! $this->guild->feature_seven_day_thread_archive) { + return reject(new RuntimeException('Guild does not have access to seven day thread archive.')); + } + break; } return $this->http->post(Endpoint::bind(Endpoint::CHANNEL_MESSAGE_THREADS, $this->channel_id, $this->id), [