diff --git a/src/Discord/Builders/MessageBuilder.php b/src/Discord/Builders/MessageBuilder.php index 704700333..1b7321e25 100644 --- a/src/Discord/Builders/MessageBuilder.php +++ b/src/Discord/Builders/MessageBuilder.php @@ -17,6 +17,7 @@ use Discord\Exceptions\FileNotFoundException; use Discord\Helpers\Multipart; use Discord\Http\Exceptions\RequestFailedException; +use Discord\Parts\Channel\Attachment; use Discord\Parts\Channel\Message; use Discord\Parts\Embed\Embed; use Discord\Parts\Guild\Sticker; @@ -66,6 +67,13 @@ class MessageBuilder implements JsonSerializable */ private $files = []; + /** + * Attachments to send with this message. + * + * @var Attachment[] + */ + private $attachments = []; + /** * Components to send with this message. * @@ -333,6 +341,50 @@ public function getComponents(): array return $this->components; } + /** + * Adds attachment(s) to the message. + * + * @param Attachment|string|int $attachment Attachment objects or IDs to add + * + * @return $this + */ + public function addAttachment(...$attachments): self + { + foreach ($attachments as $attachment) { + if ($attachment instanceof Attachment) { + $attachment = $attachment->getRawAttributes(); + } else { + $attachment = ['id' => $attachment]; + } + + $this->attachments[] = $attachment; + } + + return $this; + } + + /** + * Returns all the attachments in the message. + * + * @return Attachment[] + */ + public function getAttachments(): array + { + return $this->attachments; + } + + /** + * Removes all attachments from the message. + * + * @return $this + */ + public function clearAttachments(): self + { + $this->attachments = []; + + return $this; + } + /** * Sets the allowed mentions object of the message. * @@ -524,6 +576,10 @@ public function jsonSerialize(): array ]; } + if ($this->attachments) { + $content['attachments'] = $this->attachments; + } + if ($empty) { throw new RequestFailedException('You cannot send an empty message. Set the content or add an embed or file.'); } diff --git a/src/Discord/Discord.php b/src/Discord/Discord.php index 8ff79bc56..d1ba111fd 100644 --- a/src/Discord/Discord.php +++ b/src/Discord/Discord.php @@ -86,7 +86,7 @@ class Discord * * @var string Version. */ - public const VERSION = 'v7.0.0'; + public const VERSION = 'v7.0.2'; /** * The logger. @@ -1398,7 +1398,7 @@ public function run(): void public function close(bool $closeLoop = true): void { $this->closing = true; - $this->ws->close(Op::CLOSE_UNKNOWN_ERROR, 'discordphp closing...'); + $this->ws->close($closeLoop ? Op::CLOSE_UNKNOWN_ERROR : Op::CLOSE_NORMAL, 'discordphp closing...'); $this->emit('closed', [$this]); $this->logger->info('discord closed'); diff --git a/src/Discord/Parts/Channel/Invite.php b/src/Discord/Parts/Channel/Invite.php index b0e92ea26..fefadf237 100644 --- a/src/Discord/Parts/Channel/Invite.php +++ b/src/Discord/Parts/Channel/Invite.php @@ -36,7 +36,6 @@ * @property int|null $approximate_presence_count Approximate count of online members, returned from the GET /invites/ endpoint when with_counts is true. * @property int|null $approximate_member_count Approximate count of total members, returned from the GET /invites/ endpoint when with_counts is true. * @property Carbon|null $expires_at The expiration date of this invite, returned from the GET /invites/ endpoint when with_expiration is true. - * @property object|null $stage_instance Stage instance data if there is a public Stage instance in the Stage channel this invite is for. * @property ScheduledEvent|null $guild_scheduled_event Guild scheduled event data, only included if guild_scheduled_event_id contains a valid guild scheduled event id. * @property int $uses How many times the invite has been used. * @property int $max_uses How many times the invite can be used. @@ -60,7 +59,7 @@ class Invite extends Part 'approximate_presence_count', 'approximate_member_count', 'expires_at', - 'stage_instance', + 'stage_instance', // deprecated 'guild_scheduled_event', // Extra metadata diff --git a/src/Discord/Parts/Embed/Embed.php b/src/Discord/Parts/Embed/Embed.php index ca1aedfeb..35b18a624 100644 --- a/src/Discord/Parts/Embed/Embed.php +++ b/src/Discord/Parts/Embed/Embed.php @@ -13,6 +13,7 @@ use Carbon\Carbon; use Discord\Helpers\Collection; +use Discord\Parts\Channel\Attachment; use Discord\Parts\Part; use function Discord\poly_strlen; @@ -385,13 +386,17 @@ public function setFooter(string $text, string $iconurl = ''): self /** * Set the image of this embed. * - * @param string $url + * @param string|Attachment $url * * @return $this */ public function setImage($url): self { - $this->image = ['url' => (string) $url]; + if ($url instanceof Attachment) { + $this->image = ['url' => 'attachment://'.$url->filename]; + } else { + $this->image = ['url' => (string) $url]; + } return $this; } diff --git a/src/Discord/Parts/Thread/Thread.php b/src/Discord/Parts/Thread/Thread.php index ba73b42cc..dff8d89df 100644 --- a/src/Discord/Parts/Thread/Thread.php +++ b/src/Discord/Parts/Thread/Thread.php @@ -208,6 +208,36 @@ protected function getArchiverIdAttribute(): ?string return $this->thread_metadata->archiver_id ?? null; } + /** + * Set whether the thread is archived. + * + * @param bool $value + */ + protected function setArchivedAttribute(bool $value) + { + $this->thread_metadata->archived = $value; + } + + /** + * Set whether the thread is locked. + * + * @param bool $value + */ + protected function setLockedAttribute(bool $value) + { + $this->thread_metadata->locked = $value; + } + + /** + * Set the number of minutes of inactivity required for the thread to auto archive. + * + * @param int $value + */ + protected function setAutoArchiveDurationAttribute(int $value) + { + $this->thread_metadata->auto_archive_duration = $value; + } + /** * Returns the user who archived the thread. * @@ -311,24 +341,74 @@ public function removeMember($user): ExtendedPromiseInterface return $this->http->delete(Endpoint::bind(Endpoint::THREAD_MEMBER, $this->id, $user)); } + /** + * Rename the thread. + * + * @param string $name New thread name. + * @param string|null $reason Reason for Audit Log. + * + * @return ExtendedPromiseInterface + */ + public function rename(string $name, ?string $reason = null): ExtendedPromiseInterface + { + $headers = []; + if (isset($reason)) { + $headers['X-Audit-Log-Reason'] = $reason; + } + + return $this->http->patch(Endpoint::bind(Endpoint::THREAD, $this->id), ['name' => $name], $headers); + } + /** * Archive the thread. * + * @param string|null $reason Reason for Audit Log. + * * @return ExtendedPromiseInterface */ - public function archive(): ExtendedPromiseInterface + public function archive(?string $reason = null): ExtendedPromiseInterface { - return $this->http->patch(Endpoint::bind(Endpoint::THREAD, $this->id), ['archived' => true]); + $headers = []; + if (isset($reason)) { + $headers['X-Audit-Log-Reason'] = $reason; + } + + return $this->http->patch(Endpoint::bind(Endpoint::THREAD, $this->id), ['archived' => true], $headers); } /** * Unarchive the thread. * + * @param string|null $reason Reason for Audit Log. + * + * @return ExtendedPromiseInterface + */ + public function unarchive(?string $reason = null): ExtendedPromiseInterface + { + $headers = []; + if (isset($reason)) { + $headers['X-Audit-Log-Reason'] = $reason; + } + + return $this->http->patch(Endpoint::bind(Endpoint::THREAD, $this->id), ['archived' => false], $headers); + } + + /** + * Set auto archive duration of the thread. + * + * @param int $duration Duration in minutes. + * @param string|null $reason Reason for Audit Log. + * * @return ExtendedPromiseInterface */ - public function unarchive(): ExtendedPromiseInterface + public function setAutoArchiveDuration(int $duration, ?string $reason = null): ExtendedPromiseInterface { - return $this->http->patch(Endpoint::bind(Endpoint::THREAD, $this->id), ['archived' => false]); + $headers = []; + if (isset($reason)) { + $headers['X-Audit-Log-Reason'] = $reason; + } + + return $this->http->patch(Endpoint::bind(Endpoint::THREAD, $this->id), ['auto_archive_duration' => $duration], $headers); } /** @@ -656,6 +736,20 @@ public function createMessageCollector(callable $filter, array $options = []): E return $deferred->promise(); } + /** + * @inheritdoc + */ + public function getUpdatableAttributes(): array + { + return [ + 'name' => $this->name, + 'rate_limit_per_user' => $this->rate_limit_per_user, + 'archived' => $this->archived, + 'auto_archive_duration' => $this->auto_archive_duration, + 'locked' => $this->locked, + ]; + } + /** * @inheritdoc */ diff --git a/src/Discord/Parts/User/Member.php b/src/Discord/Parts/User/Member.php index e9287e698..19e4a3fcf 100644 --- a/src/Discord/Parts/User/Member.php +++ b/src/Discord/Parts/User/Member.php @@ -159,8 +159,8 @@ public function setNickname(?string $nick = null, ?string $reason = null): Exten /** * Moves the member to another voice channel. * - * @param Channel|string $channel The channel to move the member to. - * @param string|null $reason Reason for Audit Log. + * @param Channel|string|null $channel The channel to move the member to. + * @param string|null $reason Reason for Audit Log. * * @return ExtendedPromiseInterface */