From 8d9cd597f9777f5e42e33bcf51c26f6dad95f9de Mon Sep 17 00:00:00 2001 From: Redssu Date: Thu, 7 Nov 2024 13:01:46 +0100 Subject: [PATCH 1/3] Add support for Discord Embeds --- src/DiscordEmbed.php | 185 ++++++++++++++++++++++++++++++++++ src/DiscordEmbedAuthor.php | 72 +++++++++++++ src/DiscordEmbedField.php | 61 +++++++++++ src/DiscordEmbedFooter.php | 63 ++++++++++++ src/DiscordEmbedProvider.php | 50 +++++++++ src/DiscordEmbedUrlObject.php | 76 ++++++++++++++ src/DiscordMessage.php | 41 +++++++- 7 files changed, 547 insertions(+), 1 deletion(-) create mode 100644 src/DiscordEmbed.php create mode 100644 src/DiscordEmbedAuthor.php create mode 100644 src/DiscordEmbedField.php create mode 100644 src/DiscordEmbedFooter.php create mode 100644 src/DiscordEmbedProvider.php create mode 100644 src/DiscordEmbedUrlObject.php diff --git a/src/DiscordEmbed.php b/src/DiscordEmbed.php new file mode 100644 index 0000000..34a9720 --- /dev/null +++ b/src/DiscordEmbed.php @@ -0,0 +1,185 @@ + */ +class DiscordEmbed implements Arrayable +{ + /** The title of the embed. */ + protected string|null $title = null; + + /** The description of the embed. */ + protected string|null $description = null; + + /** The URL of the embed. */ + protected string|null $url = null; + + /** The ISO 8601 timestamp of the embed content. */ + protected string|null $timestamp = null; + + /** The color code of the embed. Hex encoded. Example: 0xFF0000 */ + protected int|null $color = null; + + /** The footer of the embed. */ + protected DiscordEmbedFooter|null $footer = null; + + /** The image of the embed. */ + protected DiscordEmbedUrlObject|null $image = null; + + /** The thumbnail of the embed. */ + protected DiscordEmbedUrlObject|null $thumbnail = null; + + /** The video of the embed. */ + protected DiscordEmbedUrlObject|null $video = null; + + /** The provider of the embed. */ + protected DiscordEmbedProvider|null $provider = null; + + /** The author of the embed. */ + protected DiscordEmbedAuthor|null $author = null; + + /** + * The fields of the embed. + * + * @var \SnoerenDevelopment\DiscordWebhook\DiscordEmbedField[] + */ + protected array $fields; + + /** Create a new Discord embed instance. */ + public static function create(): self + { + return new self; + } + + /** Set the title of the embed. */ + public function title(string $title): self + { + $this->title = $title; + return $this; + } + + /** Set the description of the embed. */ + public function description(string $description): self + { + $this->description = $description; + return $this; + } + + /** Set the URL of the embed. */ + + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** Set the ISO 8601 timestamp of the embed. */ + public function timestamp(string $timestamp): self + { + $this->timestamp = $timestamp; + return $this; + } + + /** Set the color code of the embed. Hex encoded. Example: 0xFF0000 */ + public function color(int $color): self + { + $this->color = $color; + return $this; + } + + /** Set the footer of the embed. */ + public function footer(DiscordEmbedFooter $footer): self + { + $this->footer = $footer; + return $this; + } + + /** Set the image of the embed. */ + public function image(DiscordEmbedUrlObject $image): self + { + $this->image = $image; + return $this; + } + + /** Set the thumbnail of the embed. */ + public function thumbnail(DiscordEmbedUrlObject $thumbnail): self + { + $this->thumbnail = $thumbnail; + return $this; + } + + /** Set the video of the embed. */ + public function video(DiscordEmbedUrlObject $video): self + { + $this->video = $video; + return $this; + } + + /** Set the provider of the embed. */ + public function provider(DiscordEmbedProvider $provider): self + { + $this->provider = $provider; + return $this; + } + + /** Set the author of the embed. */ + public function author(DiscordEmbedAuthor $author): self + { + $this->author = $author; + return $this; + } + + /** + * Add fields to the embed. + * + * @param \SnoerenDevelopment\DiscordWebhook\DiscordEmbedField[] $fields Fields to add. + */ + public function fields(array $fields): self + { + $this->fields = [...$this->fields, ...$fields]; + return $this; + } + + /** Add a field to the embed. */ + public function field(DiscordEmbedField $field): self + { + $this->fields = [...$this->fields, $field]; + return $this; + } + + /** + * Get the instance as an array. + * + * @return mixed[] + */ + public function toArray(): array + { + return array_filter([ + 'type' => 'rich', // This is the only type supported in webhook messages. + 'title' => $this->title, + 'description' => $this->description, + 'url' => $this->url, + 'timestamp' => $this->timestamp, + 'color' => $this->color, + 'footer' => $this->footer?->toArray(), + 'image' => $this->image?->toArray(), + 'thumbnail' => $this->thumbnail?->toArray(), + 'video' => $this->video?->toArray(), + 'provider' => $this->provider?->toArray(), + 'author' => $this->author?->toArray(), + 'fields' => array_map( + fn(DiscordEmbedField $field) => $field->toArray(), + $this->fields + ), + ], function ($value) { + if (is_array($value) && count($value) === 0) { + return false; + } + + return !is_null($value); + }); + } +} \ No newline at end of file diff --git a/src/DiscordEmbedAuthor.php b/src/DiscordEmbedAuthor.php new file mode 100644 index 0000000..7d934f0 --- /dev/null +++ b/src/DiscordEmbedAuthor.php @@ -0,0 +1,72 @@ + */ +class DiscordEmbedAuthor implements Arrayable +{ + /** The name of the embed author. */ + protected string|null $name; + + /** The url of the embed author. */ + protected string|null $url; + + /** The icon URL of the embed author. */ + protected string|null $iconUrl; + + /** The proxy icon URL of the embed author. */ + protected string|null $proxyIconUrl; + + /** Create a new Discord embed author instance. */ + public static function create(): self + { + return new self; + } + + /** Set the name of the embed author. */ + public function name(string $name): self + { + $this->name = $name; + return $this; + } + + /** Set the URL of the embed author. */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** Set the icon URL of the embed author. */ + public function iconUrl(string $iconUrl): self + { + $this->iconUrl = $iconUrl; + return $this; + } + + /** Set the proxy icon URL of the embed author. */ + public function proxyIconUrl(string $proxyIconUrl): self + { + $this->proxyIconUrl = $proxyIconUrl; + return $this; + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray(): array + { + return array_filter([ + 'name' => $this->name, + 'url' => $this->url, + 'icon_url' => $this->iconUrl, + 'proxy_icon_url' => $this->proxyIconUrl, + ], fn ($value) => !is_null($value)); + } +} \ No newline at end of file diff --git a/src/DiscordEmbedField.php b/src/DiscordEmbedField.php new file mode 100644 index 0000000..131c0eb --- /dev/null +++ b/src/DiscordEmbedField.php @@ -0,0 +1,61 @@ + */ +class DiscordEmbedField implements Arrayable +{ + /** The name of the embed field. */ + protected string|null $name; + + /** The value of the embed field. */ + protected string|null $value; + + /** Indicates whether the field should be displayed inline. */ + protected bool|null $inline; + + /** Create a new Discord embed field instance. */ + public static function create(): self + { + return new self; + } + + /** Set the name of the embed field. */ + public function name(string $name): self + { + $this->name = $name; + return $this; + } + + /** Set the value of the embed field. */ + public function value(string $value): self + { + $this->value = $value; + return $this; + } + + /** Set whether the field should be displayed inline. */ + public function inline(bool $inline): self + { + $this->inline = $inline; + return $this; + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray(): array + { + return array_filter([ + 'name' => $this->name, + 'value' => $this->value, + 'inline' => $this->inline, + ], fn ($value) => !is_null($value)); + } +} \ No newline at end of file diff --git a/src/DiscordEmbedFooter.php b/src/DiscordEmbedFooter.php new file mode 100644 index 0000000..9843706 --- /dev/null +++ b/src/DiscordEmbedFooter.php @@ -0,0 +1,63 @@ + */ +class DiscordEmbedFooter implements Arrayable +{ + /** The text of the embed footer. */ + protected string|null $text; + + /** The icon URL of the embed footer. */ + protected string|null $iconUrl; + + /** The proxy icon URL of the embed footer. */ + protected string|null $proxyIconUrl; + + /** Create a new Discord embed footer instance. */ + public static function create(): self + { + return new self; + } + + /** Set the text of the embed footer. */ + public function text(string $text): self + { + $this->text = $text; + return $this; + } + + /** Set the icon URL of the embed footer. */ + public function iconUrl(string $iconUrl): self + { + $this->iconUrl = $iconUrl; + return $this; + } + + /** Set the proxy icon URL of the embed footer. */ + public function proxyIconUrl(string $proxyIconUrl): self + { + $this->proxyIconUrl = $proxyIconUrl; + return $this; + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray(): array + { + return array_filter([ + 'text' => $this->text, + 'icon_url' => $this->iconUrl, + 'proxy_icon_url' => $this->proxyIconUrl, + ], function ($value) { + return !is_null($value); + }); + } +} \ No newline at end of file diff --git a/src/DiscordEmbedProvider.php b/src/DiscordEmbedProvider.php new file mode 100644 index 0000000..fbe58c1 --- /dev/null +++ b/src/DiscordEmbedProvider.php @@ -0,0 +1,50 @@ + */ +class DiscordEmbedProvider implements Arrayable +{ + /** The name of the embed provider. */ + protected string|null $name; + + /** The URL of the embed provider. */ + protected string|null $url; + + /** Create a new Discord embed provider instance. */ + public static function create(): self + { + return new self; + } + + /** Set the name of the embed provider. */ + public function name(string $name): self + { + $this->name = $name; + return $this; + } + + /** Set the URL of the embed provider. */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray(): array + { + return array_filter([ + 'name' => $this->name, + 'url' => $this->url, + ], fn ($value) => !is_null($value)); + } +} \ No newline at end of file diff --git a/src/DiscordEmbedUrlObject.php b/src/DiscordEmbedUrlObject.php new file mode 100644 index 0000000..6e2b955 --- /dev/null +++ b/src/DiscordEmbedUrlObject.php @@ -0,0 +1,76 @@ + + */ +class DiscordEmbedUrlObject implements Arrayable +{ + /** The URL of the embed url object. */ + protected string|null $url; + + /** The proxy URL of the embed url object. */ + protected string|null $proxyUrl; + + /** The height of the embed url object. */ + protected int|null $height; + + /** The width of the embed url object. */ + protected int|null $width; + + /** Create a new Discord embed url object instance. */ + public static function create(): self + { + return new self; + } + + /** Set the URL of the embed url object. */ + public function url(string $url): self + { + $this->url = $url; + return $this; + } + + /** Set the proxy URL of the embed url object. */ + public function proxyUrl(string $proxyUrl): self + { + $this->proxyUrl = $proxyUrl; + return $this; + } + + /** Set the height of the embed url object. */ + public function height(int $height): self + { + $this->height = $height; + return $this; + } + + /** Set the width of the embed url object. */ + public function width(int $width): self + { + $this->width = $width; + return $this; + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray(): array + { + return array_filter([ + 'url' => $this->url, + 'proxy_url' => $this->proxyUrl, + 'height' => $this->height, + 'width' => $this->width, + ], fn ($value) => !is_null($value)); + } +} \ No newline at end of file diff --git a/src/DiscordMessage.php b/src/DiscordMessage.php index cce5f90..d7121e8 100644 --- a/src/DiscordMessage.php +++ b/src/DiscordMessage.php @@ -20,6 +20,13 @@ class DiscordMessage implements Arrayable /** Indicates that this is a Text-to-speech message. */ protected ?bool $tts = null; + /** + * The embeds of the message. + * + * @var \SnoerenDevelopment\DiscordWebhook\DiscordEmbed[] + */ + protected array $embeds; + /** Create a new Discord message instance. */ public static function create(): self { @@ -62,6 +69,28 @@ public function tts(bool $tts): self return $this; } + /** + * Add the message embeds. + * + * @param \SnoerenDevelopment\DiscordWebhook\DiscordEmbed[] $embeds Embeds to add. + */ + public function embeds(array $embeds): self + { + $this->embeds = [...$this->embeds, ...$embeds]; + return $this; + } + + /** + * Add the message embed. + * + * @param \SnoerenDevelopment\DiscordWebhook\DiscordEmbed $embed The embed to add. + */ + public function embed(DiscordEmbed $embed): self + { + $this->embeds = [...$this->embeds, $embed]; + return $this; + } + /** * Get the instance as an array. * @@ -74,6 +103,16 @@ public function toArray(): array 'username' => $this->username, 'avatar_url' => $this->avatarUrl, 'tts' => $this->tts, - ], fn ($value) => !is_null($value)); + 'embeds' => array_map( + fn(DiscordEmbed $embed) => $embed->toArray(), + $this->embeds + ), + ], function ($value) { + if (is_array($value) && count($value) === 0) { + return false; + } + + return !is_null($value); + }); } } From 25ac4a1cafbbe2054a92aea02e7c3e6292a209be Mon Sep 17 00:00:00 2001 From: Redssu Date: Mon, 11 Nov 2024 17:53:23 +0100 Subject: [PATCH 2/3] Add default values on arrays --- src/DiscordEmbed.php | 2 +- src/DiscordMessage.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DiscordEmbed.php b/src/DiscordEmbed.php index 34a9720..c4fd1e0 100644 --- a/src/DiscordEmbed.php +++ b/src/DiscordEmbed.php @@ -46,7 +46,7 @@ class DiscordEmbed implements Arrayable * * @var \SnoerenDevelopment\DiscordWebhook\DiscordEmbedField[] */ - protected array $fields; + protected array $fields = []; /** Create a new Discord embed instance. */ public static function create(): self diff --git a/src/DiscordMessage.php b/src/DiscordMessage.php index d7121e8..dbd7b14 100644 --- a/src/DiscordMessage.php +++ b/src/DiscordMessage.php @@ -25,7 +25,7 @@ class DiscordMessage implements Arrayable * * @var \SnoerenDevelopment\DiscordWebhook\DiscordEmbed[] */ - protected array $embeds; + protected array $embeds = []; /** Create a new Discord message instance. */ public static function create(): self From bfb374ee45c60ae25479510f041c733f7950fa03 Mon Sep 17 00:00:00 2001 From: Redssu Date: Mon, 11 Nov 2024 17:56:29 +0100 Subject: [PATCH 3/3] Add more missing default values --- src/DiscordEmbedAuthor.php | 10 +++++----- src/DiscordEmbedField.php | 6 +++--- src/DiscordEmbedFooter.php | 6 +++--- src/DiscordEmbedProvider.php | 4 ++-- src/DiscordEmbedUrlObject.php | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/DiscordEmbedAuthor.php b/src/DiscordEmbedAuthor.php index 7d934f0..3a32197 100644 --- a/src/DiscordEmbedAuthor.php +++ b/src/DiscordEmbedAuthor.php @@ -10,16 +10,16 @@ class DiscordEmbedAuthor implements Arrayable { /** The name of the embed author. */ - protected string|null $name; + protected string|null $name = null; /** The url of the embed author. */ - protected string|null $url; + protected string|null $url = null; /** The icon URL of the embed author. */ - protected string|null $iconUrl; + protected string|null $iconUrl = null; /** The proxy icon URL of the embed author. */ - protected string|null $proxyIconUrl; + protected string|null $proxyIconUrl = null; /** Create a new Discord embed author instance. */ public static function create(): self @@ -67,6 +67,6 @@ public function toArray(): array 'url' => $this->url, 'icon_url' => $this->iconUrl, 'proxy_icon_url' => $this->proxyIconUrl, - ], fn ($value) => !is_null($value)); + ], fn($value) => !is_null($value)); } } \ No newline at end of file diff --git a/src/DiscordEmbedField.php b/src/DiscordEmbedField.php index 131c0eb..7578c71 100644 --- a/src/DiscordEmbedField.php +++ b/src/DiscordEmbedField.php @@ -10,13 +10,13 @@ class DiscordEmbedField implements Arrayable { /** The name of the embed field. */ - protected string|null $name; + protected string|null $name = null; /** The value of the embed field. */ - protected string|null $value; + protected string|null $value = null; /** Indicates whether the field should be displayed inline. */ - protected bool|null $inline; + protected bool|null $inline = null; /** Create a new Discord embed field instance. */ public static function create(): self diff --git a/src/DiscordEmbedFooter.php b/src/DiscordEmbedFooter.php index 9843706..454366e 100644 --- a/src/DiscordEmbedFooter.php +++ b/src/DiscordEmbedFooter.php @@ -10,13 +10,13 @@ class DiscordEmbedFooter implements Arrayable { /** The text of the embed footer. */ - protected string|null $text; + protected string|null $text = null; /** The icon URL of the embed footer. */ - protected string|null $iconUrl; + protected string|null $iconUrl = null; /** The proxy icon URL of the embed footer. */ - protected string|null $proxyIconUrl; + protected string|null $proxyIconUrl = null; /** Create a new Discord embed footer instance. */ public static function create(): self diff --git a/src/DiscordEmbedProvider.php b/src/DiscordEmbedProvider.php index fbe58c1..3384332 100644 --- a/src/DiscordEmbedProvider.php +++ b/src/DiscordEmbedProvider.php @@ -10,10 +10,10 @@ class DiscordEmbedProvider implements Arrayable { /** The name of the embed provider. */ - protected string|null $name; + protected string|null $name = null; /** The URL of the embed provider. */ - protected string|null $url; + protected string|null $url = null; /** Create a new Discord embed provider instance. */ public static function create(): self diff --git a/src/DiscordEmbedUrlObject.php b/src/DiscordEmbedUrlObject.php index 6e2b955..4aaedca 100644 --- a/src/DiscordEmbedUrlObject.php +++ b/src/DiscordEmbedUrlObject.php @@ -14,16 +14,16 @@ class DiscordEmbedUrlObject implements Arrayable { /** The URL of the embed url object. */ - protected string|null $url; + protected string|null $url = null; /** The proxy URL of the embed url object. */ - protected string|null $proxyUrl; + protected string|null $proxyUrl = null; /** The height of the embed url object. */ - protected int|null $height; + protected int|null $height = null; /** The width of the embed url object. */ - protected int|null $width; + protected int|null $width = null; /** Create a new Discord embed url object instance. */ public static function create(): self