From d4bf99eac61c003230ef57960acbf65a51062cb9 Mon Sep 17 00:00:00 2001 From: Slipstream Date: Wed, 11 Jun 2025 14:27:01 -0600 Subject: [PATCH] Add embed helper methods and docs (#54) --- disagreement/models.py | 38 +++++++++++++++++++++++++++++++++++-- docs/embeds.md | 22 +++++++++++++++++++++ tests/test_embed_methods.py | 18 ++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 docs/embeds.md create mode 100644 tests/test_embed_methods.py diff --git a/disagreement/models.py b/disagreement/models.py index b724249..79329a7 100644 --- a/disagreement/models.py +++ b/disagreement/models.py @@ -541,8 +541,42 @@ class Embed: payload["fields"] = [f.to_dict() for f in self.fields] return payload - # Convenience methods for building embeds can be added here - # e.g., set_author, add_field, set_footer, set_image, etc. + # Convenience methods mirroring ``discord.py``'s ``Embed`` API + + def set_author( + self, *, name: str, url: Optional[str] = None, icon_url: Optional[str] = None + ) -> "Embed": + """Set the embed author and return ``self`` for chaining.""" + + data: Dict[str, Any] = {"name": name} + if url: + data["url"] = url + if icon_url: + data["icon_url"] = icon_url + self.author = EmbedAuthor(data) + return self + + def add_field(self, *, name: str, value: str, inline: bool = False) -> "Embed": + """Add a field to the embed.""" + + field = EmbedField({"name": name, "value": value, "inline": inline}) + self.fields.append(field) + return self + + def set_footer(self, *, text: str, icon_url: Optional[str] = None) -> "Embed": + """Set the embed footer.""" + + data: Dict[str, Any] = {"text": text} + if icon_url: + data["icon_url"] = icon_url + self.footer = EmbedFooter(data) + return self + + def set_image(self, url: str) -> "Embed": + """Set the embed image.""" + + self.image = EmbedImage({"url": url}) + return self class Attachment: diff --git a/docs/embeds.md b/docs/embeds.md new file mode 100644 index 0000000..bac95c6 --- /dev/null +++ b/docs/embeds.md @@ -0,0 +1,22 @@ +# Embeds + +`Embed` objects can be constructed piece by piece much like in `discord.py`. +These helper methods return the embed instance so you can chain calls. + +```python +from disagreement.models import Embed + +embed = ( + Embed() + .set_author(name="Disagreement", url="https://example.com", icon_url="https://cdn.example.com/bot.png") + .add_field(name="Info", value="Some details") + .set_footer(text="Made with Disagreement") + .set_image(url="https://cdn.example.com/image.png") +) +``` + +Call `to_dict()` to convert the embed back to a payload dictionary before sending: + +```python +payload = embed.to_dict() +``` diff --git a/tests/test_embed_methods.py b/tests/test_embed_methods.py new file mode 100644 index 0000000..227b179 --- /dev/null +++ b/tests/test_embed_methods.py @@ -0,0 +1,18 @@ +from disagreement.models import Embed + + +def test_embed_helper_methods(): + embed = ( + Embed() + .set_author(name="name", url="url", icon_url="icon") + .add_field(name="n", value="v") + .set_footer(text="footer", icon_url="icon") + .set_image(url="https://example.com/image.png") + ) + + assert embed.author.name == "name" + assert embed.author.url == "url" + assert embed.author.icon_url == "icon" + assert len(embed.fields) == 1 and embed.fields[0].name == "n" + assert embed.footer.text == "footer" + assert embed.image.url == "https://example.com/image.png"