-
Notifications
You must be signed in to change notification settings - Fork 148
feat(flags): add new flags to Embed and update Attachment flags #1283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
e423ff4
cad882c
5ec2135
b56f99c
46fc41b
9ae0716
9f61729
b00e4d4
56c1ff9
19421ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Add :attr:`Embed.flags`, ``Embed.image.flags``, ``Embed.thumbnail.flags``, :class:`EmbedFlags`, :class:`EmbedMediaFlags` and update the :class:`AttachmentFlags`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| from . import utils | ||
| from .colour import Colour | ||
| from .file import File | ||
| from .flags import EmbedFlags, EmbedMediaFlags | ||
| from .utils import MISSING, classproperty, warn_deprecated | ||
|
|
||
| __all__ = ("Embed",) | ||
|
|
@@ -89,6 +90,7 @@ class _EmbedMediaProxy(Sized, Protocol): | |
| proxy_url: Optional[str] | ||
| height: Optional[int] | ||
| width: Optional[int] | ||
| flags: Optional[EmbedMediaFlags] | ||
|
|
||
| class _EmbedVideoProxy(Sized, Protocol): | ||
| url: Optional[str] | ||
|
|
@@ -182,6 +184,7 @@ class Embed: | |
| "_fields", | ||
| "description", | ||
| "_files", | ||
| "_flags", | ||
| ) | ||
|
|
||
| _default_colour: ClassVar[Optional[Colour]] = None | ||
|
|
@@ -220,6 +223,7 @@ def __init__( | |
| self._image: Optional[EmbedImagePayload] = None | ||
| self._footer: Optional[EmbedFooterPayload] = None | ||
| self._fields: Optional[List[EmbedFieldPayload]] = None | ||
| self._flags: Optional[int] = None | ||
|
Snipy7374 marked this conversation as resolved.
Outdated
|
||
|
|
||
| self._files: Dict[_FileKey, File] = {} | ||
|
|
||
|
|
@@ -267,12 +271,20 @@ def from_dict(cls, data: EmbedData) -> Self: | |
| self.timestamp = utils.parse_time(data.get("timestamp")) | ||
|
|
||
| self._thumbnail = data.get("thumbnail") | ||
| if self._thumbnail and (thumbnail_flags := self._thumbnail.get("flags")): | ||
| self._thumbnail["flags"] = EmbedMediaFlags._from_value(thumbnail_flags) # type: ignore | ||
|
|
||
| self._video = data.get("video") | ||
| self._provider = data.get("provider") | ||
| self._author = data.get("author") | ||
|
|
||
| self._image = data.get("image") | ||
| if self._image and (image_flags := self._image.get("flags")): | ||
| self._image["flags"] = EmbedMediaFlags._from_value(image_flags) # type: ignore | ||
|
|
||
|
Comment on lines
+266
to
+276
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like how this is done but I don't see much alternatives
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than save it here, we could make the flags when we access the image or thumbnail, no?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also no longer seems to be respected in serialisation.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What do you mean? It's not consistent with the lib?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
that was my idea as well. It's still a bit awkward, but a separate |
||
| self._footer = data.get("footer") | ||
| self._fields = data.get("fields") | ||
| self._flags = data.get("flags") | ||
|
|
||
| return self | ||
|
|
||
|
|
@@ -371,6 +383,16 @@ def timestamp(self, value: Optional[datetime.datetime]) -> None: | |
| f"Expected datetime.datetime or None received {type(value).__name__} instead" | ||
| ) | ||
|
|
||
| @property | ||
| def flags(self) -> Optional[EmbedFlags]: | ||
| """Optional[:class:`EmbedFlags`]: Returns the embed's flags. | ||
|
|
||
| .. versionadded:: 2.11 | ||
| """ | ||
| if self._flags is None: | ||
| return | ||
| return EmbedFlags._from_value(self._flags) | ||
|
onerandomusername marked this conversation as resolved.
|
||
|
|
||
| @property | ||
| def footer(self) -> _EmbedFooterProxy: | ||
| """Returns an ``EmbedProxy`` denoting the footer contents. | ||
|
|
@@ -455,6 +477,11 @@ def image(self) -> _EmbedMediaProxy: | |
| - ``proxy_url`` | ||
| - ``width`` | ||
| - ``height`` | ||
| - ``flags`` | ||
|
|
||
| .. versionchanged:: 2.11 | ||
|
Snipy7374 marked this conversation as resolved.
Outdated
|
||
|
|
||
| Added the ``flags`` attribute. | ||
|
|
||
| If an attribute is not set, it will be ``None``. | ||
| """ | ||
|
|
@@ -508,6 +535,11 @@ def thumbnail(self) -> _EmbedMediaProxy: | |
| - ``proxy_url`` | ||
| - ``width`` | ||
| - ``height`` | ||
| - ``flags`` | ||
|
|
||
| .. versionchanged:: 2.11 | ||
|
|
||
| Added the ``flags`` attribute. | ||
|
|
||
| If an attribute is not set, it will be ``None``. | ||
| """ | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -45,6 +45,8 @@ | |||||
| "SKUFlags", | ||||||
| "ApplicationInstallTypes", | ||||||
| "InteractionContextTypes", | ||||||
| "EmbedFlags", | ||||||
| "EmbedMediaFlags", | ||||||
| ) | ||||||
|
|
||||||
| BF = TypeVar("BF", bound="BaseFlags") | ||||||
|
|
@@ -2600,11 +2602,51 @@ class AttachmentFlags(BaseFlags): | |||||
| @_generated | ||||||
| def __init__(self, *, is_remix: bool = ...) -> None: ... | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_clip(self): | ||||||
| """:class:`bool`: Returns ``True`` if the attachment is a clip. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
| """ | ||||||
| return 1 << 0 | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_thumbnail(self): | ||||||
| """:class:`bool`: Returns ``True`` if the attachment is the thumbnail of a thread in a media channel. | ||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
| """ | ||||||
| return 1 << 1 | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_remix(self): | ||||||
| """:class:`bool`: Returns ``True`` if the attachment has been edited using the Remix feature.""" | ||||||
| return 1 << 2 | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_spoiler(self): | ||||||
| """:class:`bool`: Returns ``True`` if the attachment was marked as a spoiler. | ||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
| """ | ||||||
| return 1 << 3 | ||||||
|
|
||||||
| @flag_value | ||||||
| def contains_explicit_media(self): | ||||||
|
Snipy7374 marked this conversation as resolved.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This flag seems to have been removed from the docs again |
||||||
| """:class:`bool`: Returns ``True`` if the attachment was flagged as sensitive content. | ||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
| """ | ||||||
| return 1 << 4 | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_animated(self): | ||||||
| """:class:`bool`: Returns ``True`` if the attachment is an animated image. | ||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
| """ | ||||||
| return 1 << 5 | ||||||
|
|
||||||
|
|
||||||
| class SKUFlags(BaseFlags): | ||||||
| """Wraps up Discord SKU flags. | ||||||
|
|
@@ -2892,3 +2934,152 @@ def bot_dm(self): | |||||
| def private_channel(self): | ||||||
| """:class:`bool`: Returns ``True`` if the command is usable in DMs and group DMs with other users.""" | ||||||
| return 1 << 2 | ||||||
|
|
||||||
|
|
||||||
| class EmbedFlags(BaseFlags): | ||||||
| """Wraps up Discord Embed flags. | ||||||
|
|
||||||
| .. collapse:: operations | ||||||
|
|
||||||
| .. describe:: x == y | ||||||
|
|
||||||
| Checks if two EmbedFlags instances are equal. | ||||||
| .. describe:: x != y | ||||||
|
|
||||||
| Checks if two EmbedFlags instances are not equal. | ||||||
| .. describe:: x <= y | ||||||
|
|
||||||
| Checks if an EmbedFlags instance is a subset of another EmbedFlags instance. | ||||||
| .. describe:: x >= y | ||||||
|
|
||||||
| Checks if an EmbedFlags instance is a superset of another EmbedFlags instance. | ||||||
| .. describe:: x < y | ||||||
|
|
||||||
| Checks if an EmbedFlags instance is a strict subset of another EmbedFlags instance. | ||||||
| .. describe:: x > y | ||||||
|
|
||||||
| Checks if an EmbedFlags instance is a strict superset of another EmbedFlags instance. | ||||||
| .. describe:: x | y, x |= y | ||||||
|
|
||||||
| Returns a new EmbedFlags instance with all enabled flags from both x and y. | ||||||
| (Using ``|=`` will update in place). | ||||||
| .. describe:: x & y, x &= y | ||||||
|
|
||||||
| Returns a new EmbedFlags instance with only flags enabled on both x and y. | ||||||
| (Using ``&=`` will update in place). | ||||||
| .. describe:: x ^ y, x ^= y | ||||||
|
|
||||||
| Returns a new EmbedFlags instance with only flags enabled on one of x or y, but not both. | ||||||
| (Using ``^=`` will update in place). | ||||||
| .. describe:: ~x | ||||||
|
|
||||||
| Returns a new EmbedFlags instance with all flags from x inverted. | ||||||
| .. describe:: hash(x) | ||||||
|
|
||||||
| Returns the flag's hash. | ||||||
| .. describe:: iter(x) | ||||||
|
|
||||||
| Returns an iterator of ``(name, value)`` pairs. This allows it | ||||||
| to be, for example, constructed as a dict or a list of pairs. | ||||||
| Note that aliases are not shown. | ||||||
|
|
||||||
| Additionally supported are a few operations on class attributes. | ||||||
|
|
||||||
| .. describe:: EmbedFlags.y | EmbedFlags.z, EmbedFlags(y=True) | EmbedFlags.z | ||||||
|
|
||||||
| Returns an EmbedFlags instance with all provided flags enabled. | ||||||
|
|
||||||
| .. describe:: ~EmbedFlags.y | ||||||
|
|
||||||
| Returns an EmbedFlags instance with all flags except ``y`` inverted from their default value. | ||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
|
|
||||||
| Attributes | ||||||
| ---------- | ||||||
| value: :class:`int` | ||||||
| The raw value. You should query flags via the properties | ||||||
| rather than using this raw value. | ||||||
| """ | ||||||
|
|
||||||
| @flag_value | ||||||
| def contains_explicit_media(self): | ||||||
|
Snipy7374 marked this conversation as resolved.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, was removed from the docs |
||||||
| """:class:`bool`: Returns ``True`` if the embed was flagged as sensitive content.""" | ||||||
| return 1 << 4 | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_content_inventory_entry(self): | ||||||
| """:class:`bool`: Returns ``True`` if the embed is a reply to an activity card.""" | ||||||
| return 1 << 5 | ||||||
|
|
||||||
|
|
||||||
| class EmbedMediaFlags(BaseFlags): | ||||||
| """Wraps up Discord Embed media flags. | ||||||
|
|
||||||
| .. collapse:: operations | ||||||
|
|
||||||
| .. describe:: x == y | ||||||
|
|
||||||
| Checks if two EmbedMediaFlags instances are equal. | ||||||
| .. describe:: x != y | ||||||
|
|
||||||
| Checks if two EmbedMediaFlags instances are not equal. | ||||||
| .. describe:: x <= y | ||||||
|
|
||||||
| Checks if an EmbedMediaFlags instance is a subset of another EmbedMediaFlags instance. | ||||||
| .. describe:: x >= y | ||||||
|
|
||||||
| Checks if an EmbedMediaFlags instance is a superset of another EmbedMediaFlags instance. | ||||||
| .. describe:: x < y | ||||||
|
|
||||||
| Checks if an EmbedMediaFlags instance is a strict subset of another EmbedMediaFlags instance. | ||||||
| .. describe:: x > y | ||||||
|
|
||||||
| Checks if an EmbedMediaFlags instance is a strict superset of another EmbedMediaFlags instance. | ||||||
| .. describe:: x | y, x |= y | ||||||
|
|
||||||
| Returns a new EmbedMediaFlags instance with all enabled flags from both x and y. | ||||||
| (Using ``|=`` will update in place). | ||||||
| .. describe:: x & y, x &= y | ||||||
|
|
||||||
| Returns a new EmbedMediaFlags instance with only flags enabled on both x and y. | ||||||
| (Using ``&=`` will update in place). | ||||||
| .. describe:: x ^ y, x ^= y | ||||||
|
|
||||||
| Returns a new EmbedMediaFlags instance with only flags enabled on one of x or y, but not both. | ||||||
| (Using ``^=`` will update in place). | ||||||
| .. describe:: ~x | ||||||
|
|
||||||
| Returns a new EmbedMediaFlags instance with all flags from x inverted. | ||||||
| .. describe:: hash(x) | ||||||
|
|
||||||
| Returns the flag's hash. | ||||||
| .. describe:: iter(x) | ||||||
|
|
||||||
| Returns an iterator of ``(name, value)`` pairs. This allows it | ||||||
| to be, for example, constructed as a dict or a list of pairs. | ||||||
| Note that aliases are not shown. | ||||||
|
|
||||||
| Additionally supported are a few operations on class attributes. | ||||||
|
|
||||||
| .. describe:: EmbedMediaFlags.y | EmbedMediaFlags.z, EmbedMediaFlags(y=True) | EmbedMediaFlags.z | ||||||
|
|
||||||
| Returns an EmbedMediaFlags instance with all provided flags enabled. | ||||||
|
|
||||||
| .. describe:: ~EmbedMediaFlags.y | ||||||
|
|
||||||
| Returns an EmbedMediaFlags instance with all flags except ``y`` inverted from their default value. | ||||||
|
|
||||||
| .. versionadded:: 2.11 | ||||||
|
|
||||||
| Attributes | ||||||
| ---------- | ||||||
| value: :class:`int` | ||||||
| The raw value. You should query flags via the properties | ||||||
| rather than using this raw value. | ||||||
| """ | ||||||
|
|
||||||
| @flag_value | ||||||
| def is_animated(self): | ||||||
| """:class:`bool`: Returns ``True`` if the embed media is animated.""" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
"media" is plural, at least in this context (apparently it can be singular when referring to mass media?). "embed medium" also sounds a bit weird, so "embed image" seems like a good compromise to me |
||||||
| return 1 << 5 | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| ) | ||
|
|
||
| from . import utils | ||
| from .appinfo import AppInfo | ||
| from .channel import PartialMessageable | ||
| from .components import ActionRow, MessageComponent, _component_factory | ||
| from .embeds import Embed | ||
|
|
@@ -307,6 +308,21 @@ class Attachment(Hashable): | |
| (see :attr:`MessageFlags.is_voice_message`). | ||
|
|
||
| .. versionadded:: 2.9 | ||
|
|
||
| clip_participants: List[:class:`User`] | ||
| If this attachment is a clip returns a list of users who were in the stream. | ||
|
|
||
| .. versionadded:: 2.11 | ||
|
|
||
| clip_created_at: Optional[:class:`datetime.datetime`] | ||
| If this attachment is a clip returns the creation timestamp. | ||
|
|
||
| .. versionadded:: 2.11 | ||
|
|
||
| application: Optional[:class:`AppInfo`] | ||
| If this attachment is a clip returns the application in the stream, if recognized. | ||
|
|
||
| .. versionadded:: 2.11 | ||
| """ | ||
|
|
||
| __slots__ = ( | ||
|
|
@@ -325,6 +341,9 @@ class Attachment(Hashable): | |
| "duration", | ||
| "waveform", | ||
| "_flags", | ||
| "clip_participants", | ||
| "clip_created_at", | ||
| "application", | ||
| ) | ||
|
|
||
| def __init__(self, *, data: AttachmentPayload, state: ConnectionState) -> None: | ||
|
|
@@ -345,6 +364,15 @@ def __init__(self, *, data: AttachmentPayload, state: ConnectionState) -> None: | |
| b64decode(waveform_data) if (waveform_data := data.get("waveform")) else None | ||
| ) | ||
| self._flags: int = data.get("flags", 0) | ||
| self.clip_participants: List[User] = [ | ||
| User(state=state, data=d) for d in data.get("clip_participants", []) | ||
| ] | ||
| self.clip_created_at: Optional[datetime.datetime] = utils.parse_time( | ||
| data.get("clip_created_at") | ||
| ) | ||
|
Comment on lines
+373
to
+378
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are a few more non-flags-related additions in the API docs PR - I'd say this PR should either only add the new flags, or everything |
||
| self.application: Optional[AppInfo] = ( | ||
| AppInfo(state=state, data=d) if (d := data.get("application")) else None | ||
| ) | ||
|
|
||
| def is_spoiler(self) -> bool: | ||
| """Whether this attachment contains a spoiler. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this is missing the unfurled media item flags, which were added later in the API docs PR.