Skip to content

Commit 22b6361

Browse files
authored
Merge branch 'master' into feat/bypass-slowmode
Signed-off-by: Lala Sabathil <[email protected]>
2 parents 49c7944 + 5d28571 commit 22b6361

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3083
-1080
lines changed

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ These changes are available on the `master` branch, but have not yet been releas
1717
([#2711](https://github.com/Pycord-Development/pycord/pull/2711))
1818
- Added `RawMessageUpdateEvent.new_message` - message update events now contain full
1919
message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780))
20+
- Added `Guild.get_or_fetch()` and `Client.get_or_fetch()` shortcut methods.
21+
([#2776](https://github.com/Pycord-Development/pycord/pull/2776))
2022
- Added support for setting guild-specific `avatar`, `banner`, and `bio` for the bot
2123
user through `Member.edit`.
2224
([#2908](https://github.com/Pycord-Development/pycord/pull/2908))
@@ -28,13 +30,40 @@ These changes are available on the `master` branch, but have not yet been releas
2830
- Adds pre-typed and pre-constructed with select_type `ui.Select` aliases for the
2931
different select types: `ui.StringSelect`, `ui.UserSelect`, `ui.RoleSelect`,
3032
`ui.MentionableSelect`, and `ui.ChannelSelect`.
33+
- Added `store` parameter to `View` and `Modal` classes.
34+
([#2904](https://github.com/Pycord-Development/pycord/pull/2904/))
35+
- Added `Webhook.parent` and `Webhook.from_interaction`
36+
([#2904](https://github.com/Pycord-Development/pycord/pull/2904/))
37+
- Added the ability to use functions with any number of optional arguments and functions
38+
returning an awaitable as `Option.autocomplete`.
39+
([#2914](https://github.com/Pycord-Development/pycord/pull/2914))
3140
- Added `ui.FileUpload` for modals and the `FileUpload` component.
3241
([#2938](https://github.com/Pycord-Development/pycord/pull/2938))
3342
- Added `Permissions.bypass_slowmode`.
3443
([#2939](https://github.com/Pycord-Development/pycord/pull/2939))
44+
- Added support for Guild Incidents via `Guild.incidents_data` and
45+
`Guild.modify_incident_actions()`.
46+
([#2955](https://github.com/Pycord-Development/pycord/pull/2955))
3547

3648
### Changed
3749

50+
- Overhauled support for Components V2 and new Modal components
51+
([#2904](https://github.com/Pycord-Development/pycord/pull/2904/))
52+
- Revert `discord.ui.View` and `discord.ui.Modal` to 2.6.1 behavior; not compatible
53+
with new features.
54+
- Implemented `discord.ui.DesignerView` and `discord.ui.DesignerModal` to support new
55+
components.
56+
- `DesignerView` and `Container` do not support `Button` and `Select` directly; use
57+
`discord.ui.ActionRow` instead.
58+
- `DesignerModal` does not support `InputText` and `Select` directly; use
59+
`discord.ui.Label` instead.
60+
- Removed `InputText.description`, `Select.label` and `Select.description`; these are
61+
now attributes of `Label`.
62+
- `discord.ui.Item` is now a base class for `ViewItem` and `ModalItem`; all items
63+
inherit from these.
64+
- All view and modal classes now inherit from a base `ItemInterface` class, split into
65+
`BaseView` and `BaseModal`
66+
3867
### Fixed
3968

4069
- Manage silence for new SSRC with existing user_id.
@@ -58,6 +87,14 @@ These changes are available on the `master` branch, but have not yet been releas
5887
([#2938](https://github.com/Pycord-Development/pycord/pull/2938))
5988
- Fixed `TypeError` when using Python 3.12+ `type` syntax for typing slash command
6089
parameters. ([#2952](https://github.com/Pycord-Development/pycord/pull/2952))
90+
- Fixed autocomplete crashing when using an async staticmethod.
91+
([#2966](https://github.com/Pycord-Development/pycord/pull/2966))
92+
93+
### Deprecated
94+
95+
- Deprecated `utils.get_or_fetch(attr, id)` and `Client.get_or_fetch_user(id)` in favour
96+
of `utils.get_or_fetch(object_type, object_id)` and `Client.get_or_fetch(User, id)`.
97+
([#2776](https://github.com/Pycord-Development/pycord/pull/2776))
6198

6299
### Removed
63100

discord/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
from .permissions import *
6262
from .player import *
6363
from .poll import *
64+
from .primary_guild import *
6465
from .raw_models import *
6566
from .reaction import *
6667
from .role import *

discord/abc.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
from .types.channel import GuildChannel as GuildChannelPayload
9696
from .types.channel import OverwriteType
9797
from .types.channel import PermissionOverwrite as PermissionOverwritePayload
98-
from .ui.view import View
98+
from .ui.view import BaseView
9999
from .user import ClientUser
100100

101101
PartialMessageableChannel = Union[
@@ -1355,7 +1355,7 @@ async def send(
13551355
allowed_mentions: AllowedMentions = ...,
13561356
reference: Message | MessageReference | PartialMessage = ...,
13571357
mention_author: bool = ...,
1358-
view: View = ...,
1358+
view: BaseView = ...,
13591359
poll: Poll = ...,
13601360
suppress: bool = ...,
13611361
silent: bool = ...,
@@ -1376,7 +1376,7 @@ async def send(
13761376
allowed_mentions: AllowedMentions = ...,
13771377
reference: Message | MessageReference | PartialMessage = ...,
13781378
mention_author: bool = ...,
1379-
view: View = ...,
1379+
view: BaseView = ...,
13801380
poll: Poll = ...,
13811381
suppress: bool = ...,
13821382
silent: bool = ...,
@@ -1397,7 +1397,7 @@ async def send(
13971397
allowed_mentions: AllowedMentions = ...,
13981398
reference: Message | MessageReference | PartialMessage = ...,
13991399
mention_author: bool = ...,
1400-
view: View = ...,
1400+
view: BaseView = ...,
14011401
poll: Poll = ...,
14021402
suppress: bool = ...,
14031403
silent: bool = ...,
@@ -1418,7 +1418,7 @@ async def send(
14181418
allowed_mentions: AllowedMentions = ...,
14191419
reference: Message | MessageReference | PartialMessage = ...,
14201420
mention_author: bool = ...,
1421-
view: View = ...,
1421+
view: BaseView = ...,
14221422
poll: Poll = ...,
14231423
suppress: bool = ...,
14241424
silent: bool = ...,
@@ -1509,7 +1509,7 @@ async def send(
15091509
If set, overrides the :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions``.
15101510
15111511
.. versionadded:: 1.6
1512-
view: :class:`discord.ui.View`
1512+
view: :class:`discord.ui.BaseView`
15131513
A Discord UI View to add to the message.
15141514
embeds: List[:class:`~discord.Embed`]
15151515
A list of embeds to upload. Must be a maximum of 10.
@@ -1611,7 +1611,7 @@ async def send(
16111611
if view:
16121612
if not hasattr(view, "__discord_ui_view__"):
16131613
raise InvalidArgument(
1614-
f"view parameter must be View not {view.__class__!r}"
1614+
f"view parameter must be BaseView not {view.__class__!r}"
16151615
)
16161616

16171617
components = view.to_components()

discord/channel.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
from .types.channel import VoiceChannelEffectSendEvent as VoiceChannelEffectSend
108108
from .types.snowflake import SnowflakeList
109109
from .types.threads import ThreadArchiveDuration
110-
from .ui.view import View
110+
from .ui.view import BaseView
111111
from .user import BaseUser, ClientUser, User
112112
from .webhook import Webhook
113113

@@ -1217,7 +1217,7 @@ async def create_thread(
12171217
delete_message_after: float | None = None,
12181218
nonce: int | str | None = None,
12191219
allowed_mentions: AllowedMentions | None = None,
1220-
view: View | None = None,
1220+
view: BaseView | None = None,
12211221
applied_tags: list[ForumTag] | None = None,
12221222
suppress: bool = False,
12231223
silent: bool = False,
@@ -1262,7 +1262,7 @@ async def create_thread(
12621262
to the object, otherwise it uses the attributes set in :attr:`~discord.Client.allowed_mentions`.
12631263
If no object is passed at all then the defaults given by :attr:`~discord.Client.allowed_mentions`
12641264
are used instead.
1265-
view: :class:`discord.ui.View`
1265+
view: :class:`discord.ui.BaseView`
12661266
A Discord UI View to add to the message.
12671267
applied_tags: List[:class:`discord.ForumTag`]
12681268
A list of tags to apply to the new thread.
@@ -1328,7 +1328,7 @@ async def create_thread(
13281328
if view:
13291329
if not hasattr(view, "__discord_ui_view__"):
13301330
raise InvalidArgument(
1331-
f"view parameter must be View not {view.__class__!r}"
1331+
f"view parameter must be BaseView not {view.__class__!r}"
13321332
)
13331333

13341334
components = view.to_components()

discord/client.py

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@
3131
import sys
3232
import traceback
3333
from types import TracebackType
34-
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Generator, Sequence, TypeVar
34+
from typing import (
35+
TYPE_CHECKING,
36+
Any,
37+
Callable,
38+
Coroutine,
39+
Generator,
40+
Sequence,
41+
TypeVar,
42+
)
3543

3644
import aiohttp
3745

@@ -59,22 +67,30 @@
5967
from .sticker import GuildSticker, StandardSticker, StickerPack, _sticker_factory
6068
from .template import Template
6169
from .threads import Thread
62-
from .ui.view import View
70+
from .ui.view import BaseView
6371
from .user import ClientUser, User
64-
from .utils import MISSING
72+
from .utils import _D, _FETCHABLE, MISSING
6573
from .voice_client import VoiceClient
6674
from .webhook import Webhook
6775
from .widget import Widget
6876

6977
if TYPE_CHECKING:
7078
from .abc import GuildChannel, PrivateChannel, Snowflake, SnowflakeTime
71-
from .channel import DMChannel
79+
from .channel import (
80+
CategoryChannel,
81+
DMChannel,
82+
ForumChannel,
83+
StageChannel,
84+
TextChannel,
85+
VoiceChannel,
86+
)
7287
from .interactions import Interaction
7388
from .member import Member
7489
from .message import Message
7590
from .poll import Poll
7691
from .soundboard import SoundboardSound
77-
from .ui.item import Item
92+
from .threads import Thread, ThreadMember
93+
from .ui.item import Item, ViewItem
7894
from .voice_client import VoiceProtocol
7995

8096
__all__ = ("Client",)
@@ -546,19 +562,19 @@ async def on_error(self, event_method: str, *args: Any, **kwargs: Any) -> None:
546562
traceback.print_exc()
547563

548564
async def on_view_error(
549-
self, error: Exception, item: Item, interaction: Interaction
565+
self, error: Exception, item: ViewItem, interaction: Interaction
550566
) -> None:
551567
"""|coro|
552568
553569
The default view error handler provided by the client.
554570
555-
This only fires for a view if you did not define its :func:`~discord.ui.View.on_error`.
571+
This only fires for a view if you did not define its :func:`~discord.ui.BaseView.on_error`.
556572
557573
Parameters
558574
----------
559575
error: :class:`Exception`
560576
The exception that was raised.
561-
item: :class:`Item`
577+
item: :class:`ViewItem`
562578
The item that the user interacted with.
563579
interaction: :class:`Interaction`
564580
The interaction that was received.
@@ -1165,7 +1181,12 @@ def get_all_members(self) -> Generator[Member]:
11651181
for guild in self.guilds:
11661182
yield from guild.members
11671183

1168-
async def get_or_fetch_user(self, id: int, /) -> User | None:
1184+
@utils.deprecated(
1185+
instead="Client.get_or_fetch(User, id)",
1186+
since="2.7",
1187+
removed="3.0",
1188+
)
1189+
async def get_or_fetch_user(self, id: int, /) -> User | None: # TODO: Remove in 3.0
11691190
"""|coro|
11701191
11711192
Looks up a user in the user cache or fetches if not found.
@@ -1181,7 +1202,49 @@ async def get_or_fetch_user(self, id: int, /) -> User | None:
11811202
The user or ``None`` if not found.
11821203
"""
11831204

1184-
return await utils.get_or_fetch(obj=self, attr="user", id=id, default=None)
1205+
return await self.get_or_fetch(object_type=User, object_id=id, default=None)
1206+
1207+
async def get_or_fetch(
1208+
self: Client,
1209+
object_type: type[_FETCHABLE],
1210+
object_id: int | None,
1211+
default: _D = None,
1212+
) -> _FETCHABLE | _D | None:
1213+
"""
1214+
Shortcut method to get data from an object either by returning the cached version, or if it does not exist, attempting to fetch it from the API.
1215+
1216+
Parameters
1217+
----------
1218+
object_type: Type[:class:`VoiceChannel` | :class:`TextChannel` | :class:`ForumChannel` | :class:`StageChannel` | :class:`CategoryChannel` | :class:`Thread` | :class:`User` | :class:`Guild` | :class:`GuildEmoji` | :class:`AppEmoji`]
1219+
Type of object to fetch or get.
1220+
1221+
object_id: :class:`int` | :data:`None`
1222+
ID of object to get. If :data:`None`, returns `default` if provided, else :data:`None`.
1223+
1224+
default: Any | :data:`None`
1225+
A default to return instead of raising if fetch fails.
1226+
1227+
Returns
1228+
-------
1229+
:class:`VoiceChannel` | :class:`TextChannel` | :class:`ForumChannel` | :class:`StageChannel` | :class:`CategoryChannel` | :class:`Thread` | :class:`User` | :class:`Guild` | :class:`GuildEmoji` | :class:`AppEmoji` | :data:`None`
1230+
The object if found, or `default` if provided when not found.
1231+
1232+
Raises
1233+
------
1234+
:exc:`TypeError`
1235+
Raised when required parameters are missing or invalid types are provided.
1236+
:exc:`InvalidArgument`
1237+
Raised when an unsupported or incompatible object type is used.
1238+
"""
1239+
try:
1240+
return await utils.get_or_fetch(
1241+
obj=self,
1242+
object_type=object_type,
1243+
object_id=object_id,
1244+
default=default,
1245+
)
1246+
except (HTTPException, ValueError, InvalidData):
1247+
return default
11851248

11861249
# listeners/waiters
11871250

@@ -2037,8 +2100,8 @@ async def create_dm(self, user: Snowflake) -> DMChannel:
20372100
data = await state.http.start_private_message(user.id)
20382101
return state.add_dm_channel(data)
20392102

2040-
def add_view(self, view: View, *, message_id: int | None = None) -> None:
2041-
"""Registers a :class:`~discord.ui.View` for persistent listening.
2103+
def add_view(self, view: BaseView, *, message_id: int | None = None) -> None:
2104+
"""Registers a :class:`~discord.ui.BaseView` for persistent listening.
20422105
20432106
This method should be used for when a view is comprised of components
20442107
that last longer than the lifecycle of the program.
@@ -2047,7 +2110,7 @@ def add_view(self, view: View, *, message_id: int | None = None) -> None:
20472110
20482111
Parameters
20492112
----------
2050-
view: :class:`discord.ui.View`
2113+
view: :class:`discord.ui.BaseView`
20512114
The view to register for dispatching.
20522115
message_id: Optional[:class:`int`]
20532116
The message ID that the view is attached to. This is currently used to
@@ -2063,8 +2126,8 @@ def add_view(self, view: View, *, message_id: int | None = None) -> None:
20632126
and all their components have an explicitly provided ``custom_id``.
20642127
"""
20652128

2066-
if not isinstance(view, View):
2067-
raise TypeError(f"expected an instance of View not {view.__class__!r}")
2129+
if not isinstance(view, BaseView):
2130+
raise TypeError(f"expected an instance of BaseView not {view.__class__!r}")
20682131

20692132
if not view.is_persistent():
20702133
raise ValueError(
@@ -2075,7 +2138,7 @@ def add_view(self, view: View, *, message_id: int | None = None) -> None:
20752138
self._connection.store_view(view, message_id)
20762139

20772140
@property
2078-
def persistent_views(self) -> Sequence[View]:
2141+
def persistent_views(self) -> Sequence[BaseView]:
20792142
"""A sequence of persistent views added to the client.
20802143
20812144
.. versionadded:: 2.0

discord/commands/core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,13 +1119,13 @@ async def invoke_autocomplete_callback(self, ctx: AutocompleteContext):
11191119
ctx.value = op.get("value")
11201120
ctx.options = values
11211121

1122-
if len(inspect.signature(option.autocomplete).parameters) == 2:
1122+
if option.autocomplete._is_instance_method:
11231123
instance = getattr(option.autocomplete, "__self__", ctx.cog)
11241124
result = option.autocomplete(instance, ctx)
11251125
else:
11261126
result = option.autocomplete(ctx)
11271127

1128-
if asyncio.iscoroutinefunction(option.autocomplete):
1128+
if inspect.isawaitable(result):
11291129
result = await result
11301130

11311131
choices = [

0 commit comments

Comments
 (0)