Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into fix-is-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Paillat-dev committed Jan 6, 2025
2 parents 5ba6fa9 + f0c8e53 commit fb3f1b9
Show file tree
Hide file tree
Showing 40 changed files with 318 additions and 136 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repos:
# - --remove-duplicate-keys
# - --remove-unused-variables
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.0
rev: v3.19.1
hooks:
- id: pyupgrade
exclude: \.(po|pot|yml|yaml)$
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ These changes are available on the `master` branch, but have not yet been releas
`Permissions.use_external_sounds`, and
`Permissions.view_creator_monetization_analytics`.
([#2620](https://github.com/Pycord-Development/pycord/pull/2620))
- Added `Message._raw_data` attribute.
([#2670](https://github.com/Pycord-Development/pycord/pull/2670))
- Added helper methods to determine the authorizing party of an `Interaction`.
([#2659](https://github.com/Pycord-Development/pycord/pull/2659))
- Added `VoiceMessage` subclass of `File` to allow voice messages to be sent.
([#2579](https://github.com/Pycord-Development/pycord/pull/2579))

### Fixed

Expand Down Expand Up @@ -67,6 +73,12 @@ These changes are available on the `master` branch, but have not yet been releas
apps. ([#2650](https://github.com/Pycord-Development/pycord/pull/2650))
- Fixed type annotations of cached properties.
([#2635](https://github.com/Pycord-Development/pycord/issues/2635))
- Fixed an error when responding non-ephemerally with a `Paginator` to an ephemerally
deferred interaction.
([#2661](https://github.com/Pycord-Development/pycord/pull/2661))
- Fixed attachment metadata being set incorrectly in interaction responses causing the
metadata to be ignored by Discord.
([#2679](https://github.com/Pycord-Development/pycord/pull/2679))

### Changed

Expand All @@ -80,6 +92,8 @@ These changes are available on the `master` branch, but have not yet been releas
- Replaced audioop (deprecated module) implementation of `PCMVolumeTransformer.read`
method with a pure Python equivalent.
([#2176](https://github.com/Pycord-Development/pycord/pull/2176))
- Updated `Guild.filesize_limit` to 10 MB instead of 25 MB following Discord's API
changes. ([#2671](https://github.com/Pycord-Development/pycord/pull/2671))

### Deprecated

Expand Down
38 changes: 0 additions & 38 deletions discord/_typed_dict.py

This file was deleted.

2 changes: 1 addition & 1 deletion discord/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import warnings
from importlib.metadata import PackageNotFoundError, version

from ._typed_dict import TypedDict
from typing_extensions import TypedDict

__all__ = ("__version__", "VersionInfo", "version_info")

Expand Down
34 changes: 9 additions & 25 deletions discord/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from .context_managers import Typing
from .enums import ChannelType
from .errors import ClientException, InvalidArgument
from .file import File
from .file import File, VoiceMessage
from .flags import MessageFlags
from .invite import Invite
from .iterators import HistoryIterator
Expand Down Expand Up @@ -1569,7 +1569,7 @@ async def send(
flags = MessageFlags(
suppress_embeds=bool(suppress),
suppress_notifications=bool(silent),
).value
)

if stickers is not None:
stickers = [sticker.id for sticker in stickers]
Expand Down Expand Up @@ -1615,27 +1615,7 @@ async def send(
if file is not None:
if not isinstance(file, File):
raise InvalidArgument("file parameter must be File")

try:
data = await state.http.send_files(
channel.id,
files=[file],
allowed_mentions=allowed_mentions,
content=content,
tts=tts,
embed=embed,
embeds=embeds,
nonce=nonce,
enforce_nonce=enforce_nonce,
message_reference=reference,
stickers=stickers,
components=components,
flags=flags,
poll=poll,
)
finally:
file.close()

files = [file]
elif files is not None:
if len(files) > 10:
raise InvalidArgument(
Expand All @@ -1644,6 +1624,10 @@ async def send(
elif not all(isinstance(file, File) for file in files):
raise InvalidArgument("files parameter must be a list of File")

if files is not None:
flags = flags + MessageFlags(
is_voice_message=any(isinstance(f, VoiceMessage) for f in files)
)
try:
data = await state.http.send_files(
channel.id,
Expand All @@ -1658,7 +1642,7 @@ async def send(
message_reference=reference,
stickers=stickers,
components=components,
flags=flags,
flags=flags.value,
poll=poll,
)
finally:
Expand All @@ -1677,7 +1661,7 @@ async def send(
message_reference=reference,
stickers=stickers,
components=components,
flags=flags,
flags=flags.value,
poll=poll,
)

Expand Down
34 changes: 34 additions & 0 deletions discord/commands/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,40 @@ def cog(self) -> Cog | None:

return self.command.cog

def is_guild_authorised(self) -> bool:
""":class:`bool`: Checks if the invoked command is guild-installed.
This is a shortcut for :meth:`Interaction.is_guild_authorised`.
There is an alias for this called :meth:`.is_guild_authorized`.
.. versionadded:: 2.7
"""
return self.interaction.is_guild_authorised()

def is_user_authorised(self) -> bool:
""":class:`bool`: Checks if the invoked command is user-installed.
This is a shortcut for :meth:`Interaction.is_user_authorised`.
There is an alias for this called :meth:`.is_user_authorized`.
.. versionadded:: 2.7
"""
return self.interaction.is_user_authorised()

def is_guild_authorized(self) -> bool:
""":class:`bool`: An alias for :meth:`.is_guild_authorised`.
.. versionadded:: 2.7
"""
return self.is_guild_authorised()

def is_user_authorized(self) -> bool:
""":class:`bool`: An alias for :meth:`.is_user_authorised`.
.. versionadded:: 2.7
"""
return self.is_user_authorised()


class AutocompleteContext:
"""Represents context for a slash command's option autocomplete.
Expand Down
2 changes: 1 addition & 1 deletion discord/ext/pages/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ async def respond(
)
# convert from WebhookMessage to Message reference to bypass
# 15min webhook token timeout (non-ephemeral messages only)
if not ephemeral:
if not ephemeral and not msg.flags.ephemeral:
msg = await msg.channel.fetch_message(msg.id)
else:
msg = await interaction.response.send_message(
Expand Down
63 changes: 62 additions & 1 deletion discord/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
import os
from typing import TYPE_CHECKING

__all__ = ("File",)
__all__ = (
"File",
"VoiceMessage",
)


class File:
Expand Down Expand Up @@ -89,6 +92,7 @@ def __init__(
description: str | None = None,
spoiler: bool = False,
):

if isinstance(fp, io.IOBase):
if not (fp.seekable() and fp.readable()):
raise ValueError(f"File buffer {fp!r} must be seekable and readable")
Expand Down Expand Up @@ -143,3 +147,60 @@ def close(self) -> None:
self.fp.close = self._closer
if self._owner:
self._closer()


class VoiceMessage(File):
"""A special case of the File class that represents a voice message.
.. versionadded:: 2.7
.. note::
Similar to File objects, VoiceMessage objects are single use and are not meant to be reused in
multiple requests.
Attributes
----------
fp: Union[:class:`os.PathLike`, :class:`io.BufferedIOBase`]
A audio file-like object opened in binary mode and read mode
or a filename representing a file in the hard drive to
open.
.. note::
If the file-like object passed is opened via ``open`` then the
modes 'rb' should be used.
To pass binary data, consider usage of ``io.BytesIO``.
filename: Optional[:class:`str`]
The filename to display when uploading to Discord.
If this is not given then it defaults to ``fp.name`` or if ``fp`` is
a string then the ``filename`` will default to the string given.
description: Optional[:class:`str`]
The description of a file, used by Discord to display alternative text on images.
spoiler: :class:`bool`
Whether the attachment is a spoiler.
waveform: Optional[:class:`str`]
The base64 encoded bytearray representing a sampled waveform.
duration_secs: Optional[:class:`float`]
The duration of the voice message.
"""

__slots__ = (
"waveform",
"duration_secs",
)

def __init__(
self,
fp: str | bytes | os.PathLike | io.BufferedIOBase,
filename: str | None = None,
*,
waveform: str = "",
duration_secs: float = 0.0,
**kwargs,
):
super().__init__(fp, filename, **kwargs)
self.waveform = waveform
self.duration_secs = duration_secs
10 changes: 5 additions & 5 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,11 @@ class Guild(Hashable):
)

_PREMIUM_GUILD_LIMITS: ClassVar[dict[int | None, _GuildLimit]] = {
None: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=26214400),
0: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=26214400),
1: _GuildLimit(emoji=100, stickers=15, bitrate=128e3, filesize=26214400),
2: _GuildLimit(emoji=150, stickers=30, bitrate=256e3, filesize=52428800),
3: _GuildLimit(emoji=250, stickers=60, bitrate=384e3, filesize=104857600),
None: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=10_485_760),
0: _GuildLimit(emoji=50, stickers=5, bitrate=96e3, filesize=10_485_760),
1: _GuildLimit(emoji=100, stickers=15, bitrate=128e3, filesize=10_485_760),
2: _GuildLimit(emoji=150, stickers=30, bitrate=256e3, filesize=52_428_800),
3: _GuildLimit(emoji=250, stickers=60, bitrate=384e3, filesize=104_857_600),
}

def __init__(self, *, data: GuildPayload, state: ConnectionState):
Expand Down
37 changes: 23 additions & 14 deletions discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
LoginFailure,
NotFound,
)
from .file import VoiceMessage
from .gateway import DiscordClientWebSocketResponse
from .utils import MISSING, warn_deprecated

Expand Down Expand Up @@ -567,13 +568,17 @@ def send_multipart_helper(
attachments = []
form.append({"name": "payload_json"})
for index, file in enumerate(files):
attachments.append(
{
"id": index,
"filename": file.filename,
"description": file.description,
}
)
attachment_info = {
"id": index,
"filename": file.filename,
"description": file.description,
}
if isinstance(file, VoiceMessage):
attachment_info.update(
waveform=file.waveform,
duration_secs=file.duration_secs,
)
attachments.append(attachment_info)
form.append(
{
"name": f"files[{index}]",
Expand Down Expand Up @@ -633,13 +638,17 @@ def edit_multipart_helper(
attachments = []
form.append({"name": "payload_json"})
for index, file in enumerate(files):
attachments.append(
{
"id": index,
"filename": file.filename,
"description": file.description,
}
)
attachment_info = {
"id": index,
"filename": file.filename,
"description": file.description,
}
if isinstance(file, VoiceMessage):
attachment_info.update(
waveform=file.waveform,
duration_secs=file.duration_secs,
)
attachments.append(attachment_info)
form.append(
{
"name": f"files[{index}]",
Expand Down
Loading

0 comments on commit fb3f1b9

Please sign in to comment.