Skip to content

Commit 90f9023

Browse files
authored
feat: Implement Attachmentflags and Attachment expiry attributes (Pycord-Development#2342)
1 parent bdf604d commit 90f9023

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

discord/flags.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
__all__ = (
3333
"SystemChannelFlags",
3434
"MessageFlags",
35+
"AttachmentFlags",
3536
"PublicUserFlags",
3637
"Intents",
3738
"MemberCacheFlags",
@@ -1485,3 +1486,68 @@ def require_tag(self):
14851486
.. versionadded:: 2.2
14861487
"""
14871488
return 1 << 4
1489+
1490+
1491+
@fill_with_flags()
1492+
class AttachmentFlags(BaseFlags):
1493+
r"""Wraps up the Discord Attachment flags.
1494+
1495+
See :class:`SystemChannelFlags`.
1496+
1497+
.. container:: operations
1498+
1499+
.. describe:: x == y
1500+
1501+
Checks if two flags are equal.
1502+
.. describe:: x != y
1503+
1504+
Checks if two flags are not equal.
1505+
.. describe:: x + y
1506+
1507+
Adds two flags together. Equivalent to ``x | y``.
1508+
.. describe:: x - y
1509+
1510+
Subtracts two flags from each other.
1511+
.. describe:: x | y
1512+
1513+
Returns the union of two flags. Equivalent to ``x + y``.
1514+
.. describe:: x & y
1515+
1516+
Returns the intersection of two flags.
1517+
.. describe:: ~x
1518+
1519+
Returns the inverse of a flag.
1520+
.. describe:: hash(x)
1521+
1522+
Return the flag's hash.
1523+
.. describe:: iter(x)
1524+
1525+
Returns an iterator of ``(name, value)`` pairs. This allows it
1526+
to be, for example, constructed as a dict or a list of pairs.
1527+
1528+
.. versionadded:: 2.5
1529+
1530+
Attributes
1531+
-----------
1532+
value: :class:`int`
1533+
The raw value. This value is a bit array field of a 53-bit integer
1534+
representing the currently available flags. You should query
1535+
flags via the properties rather than using this raw value.
1536+
"""
1537+
1538+
__slots__ = ()
1539+
1540+
@flag_value
1541+
def is_clip(self):
1542+
""":class:`bool`: Returns ``True`` if the attachment is a clip."""
1543+
return 1 << 0
1544+
1545+
@flag_value
1546+
def is_thumbnail(self):
1547+
""":class:`bool`: Returns ``True`` if the attachment is a thumbnail."""
1548+
return 1 << 1
1549+
1550+
@flag_value
1551+
def is_remix(self):
1552+
""":class:`bool`: Returns ``True`` if the attachment has been remixed."""
1553+
return 1 << 2

discord/message.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
Union,
4040
overload,
4141
)
42+
from urllib.parse import parse_qs, urlparse
4243

4344
from . import utils
4445
from .components import _component_factory
@@ -47,7 +48,7 @@
4748
from .enums import ChannelType, MessageType, try_enum
4849
from .errors import InvalidArgument
4950
from .file import File
50-
from .flags import MessageFlags
51+
from .flags import AttachmentFlags, MessageFlags
5152
from .guild import Guild
5253
from .member import Member
5354
from .mixins import Hashable
@@ -178,6 +179,16 @@ class Attachment(Hashable):
178179
waveform: Optional[:class:`str`]
179180
The base64 encoded bytearray representing a sampled waveform (currently for voice messages).
180181
182+
.. versionadded:: 2.5
183+
184+
flags: :class:`AttachmentFlags`
185+
Extra attributes of the attachment.
186+
187+
.. versionadded:: 2.5
188+
189+
hm: :class:`str`
190+
The unique signature of this attachment's instance.
191+
181192
.. versionadded:: 2.5
182193
"""
183194

@@ -195,6 +206,10 @@ class Attachment(Hashable):
195206
"description",
196207
"duration_secs",
197208
"waveform",
209+
"flags",
210+
"_ex",
211+
"_is",
212+
"hm",
198213
)
199214

200215
def __init__(self, *, data: AttachmentPayload, state: ConnectionState):
@@ -211,6 +226,32 @@ def __init__(self, *, data: AttachmentPayload, state: ConnectionState):
211226
self.description: str | None = data.get("description")
212227
self.duration_secs: float | None = data.get("duration_secs")
213228
self.waveform: str | None = data.get("waveform")
229+
self.flags: AttachmentFlags = AttachmentFlags._from_value(data.get("flags", 0))
230+
self._ex: str | None = None
231+
self._is: str | None = None
232+
self.hm: str | None = None
233+
234+
query = urlparse(self.url).query
235+
extras = ["_ex", "_is", "hm"]
236+
if query_params := parse_qs(query):
237+
for attr in extras:
238+
value = "".join(query_params.get(attr.replace("_", ""), []))
239+
if value:
240+
setattr(self, attr, value)
241+
242+
@property
243+
def expires_at(self) -> datetime.datetime:
244+
"""This attachment URL's expiry time in UTC."""
245+
if not self._ex:
246+
return None
247+
return datetime.datetime.utcfromtimestamp(int(self._ex, 16))
248+
249+
@property
250+
def issued_at(self) -> datetime.datetime:
251+
"""The attachment URL's issue time in UTC."""
252+
if not self._is:
253+
return None
254+
return datetime.datetime.utcfromtimestamp(int(self._is, 16))
214255

215256
def is_spoiler(self) -> bool:
216257
"""Whether this attachment contains a spoiler."""

discord/types/message.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Attachment(TypedDict):
7474
proxy_url: str
7575
duration_secs: NotRequired[float]
7676
waveform: NotRequired[str]
77+
flags: NotRequired[int]
7778

7879

7980
MessageActivityType = Literal[1, 2, 3, 5]

docs/api/data_classes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ Flags
118118
.. autoclass:: MessageFlags()
119119
:members:
120120

121+
.. attributetable:: AttachmentFlags
122+
123+
.. autoclass:: AttachmentFlags()
124+
:members:
125+
121126
.. attributetable:: PublicUserFlags
122127

123128
.. autoclass:: PublicUserFlags()

0 commit comments

Comments
 (0)