diff --git a/discord/activity.py b/discord/activity.py index 324bea42f..0fc0faa64 100644 --- a/discord/activity.py +++ b/discord/activity.py @@ -418,7 +418,7 @@ class Game(BaseActivity): return str(self.name) def __repr__(self) -> str: - return f'' + return f'' def to_dict(self) -> Dict[str, Any]: timestamps: Dict[str, Any] = {} @@ -514,7 +514,7 @@ class Streaming(BaseActivity): return str(self.name) def __repr__(self) -> str: - return f'' + return f'' @property def twitch_name(self) -> Optional[str]: diff --git a/discord/app_commands/installs.py b/discord/app_commands/installs.py index 5ac033245..e00d13724 100644 --- a/discord/app_commands/installs.py +++ b/discord/app_commands/installs.py @@ -57,6 +57,9 @@ class AppInstallationType: self._guild: Optional[bool] = guild self._user: Optional[bool] = user + def __repr__(self): + return f'' + @property def guild(self) -> bool: """:class:`bool`: Whether the integration is a guild install.""" @@ -142,6 +145,9 @@ class AppCommandContext: self._dm_channel: Optional[bool] = dm_channel self._private_channel: Optional[bool] = private_channel + def __repr__(self) -> str: + return f'' + @property def guild(self) -> bool: """:class:`bool`: Whether the context allows usage in a guild.""" diff --git a/discord/app_commands/models.py b/discord/app_commands/models.py index e8a96784b..dcf70d41e 100644 --- a/discord/app_commands/models.py +++ b/discord/app_commands/models.py @@ -1063,6 +1063,9 @@ class AppCommandPermissions: self.target: Union[Object, User, Member, Role, AllChannels, GuildChannel] = _object + def __repr__(self) -> str: + return f'' + def to_dict(self) -> ApplicationCommandPermissions: return { 'id': self.target.id, @@ -1106,6 +1109,9 @@ class GuildAppCommandPermissions: AppCommandPermissions(data=value, guild=guild, state=self._state) for value in data['permissions'] ] + def __repr__(self) -> str: + return f'' + def to_dict(self) -> Dict[str, Any]: return {'permissions': [p.to_dict() for p in self.permissions]} diff --git a/discord/app_commands/transformers.py b/discord/app_commands/transformers.py index c18485d8c..212991cbe 100644 --- a/discord/app_commands/transformers.py +++ b/discord/app_commands/transformers.py @@ -52,7 +52,7 @@ from ..channel import StageChannel, VoiceChannel, TextChannel, CategoryChannel, from ..abc import GuildChannel from ..threads import Thread from ..enums import Enum as InternalEnum, AppCommandOptionType, ChannelType, Locale -from ..utils import MISSING, maybe_coroutine +from ..utils import MISSING, maybe_coroutine, _human_join from ..user import User from ..role import Role from ..member import Member @@ -631,7 +631,7 @@ class BaseChannelTransformer(Transformer[ClientT]): display_name = channel_types[0].__name__ types = CHANNEL_TO_TYPES[channel_types[0]] else: - display_name = '{}, and {}'.format(', '.join(t.__name__ for t in channel_types[:-1]), channel_types[-1].__name__) + display_name = _human_join([t.__name__ for t in channel_types]) types = [] for t in channel_types: @@ -689,6 +689,7 @@ CHANNEL_TO_TYPES: Dict[Any, List[ChannelType]] = { ChannelType.news, ChannelType.category, ChannelType.forum, + ChannelType.media, ], GuildChannel: [ ChannelType.stage_voice, @@ -697,6 +698,7 @@ CHANNEL_TO_TYPES: Dict[Any, List[ChannelType]] = { ChannelType.news, ChannelType.category, ChannelType.forum, + ChannelType.media, ], AppCommandThread: [ChannelType.news_thread, ChannelType.private_thread, ChannelType.public_thread], Thread: [ChannelType.news_thread, ChannelType.private_thread, ChannelType.public_thread], @@ -704,7 +706,7 @@ CHANNEL_TO_TYPES: Dict[Any, List[ChannelType]] = { VoiceChannel: [ChannelType.voice], TextChannel: [ChannelType.text, ChannelType.news], CategoryChannel: [ChannelType.category], - ForumChannel: [ChannelType.forum], + ForumChannel: [ChannelType.forum, ChannelType.media], } BUILT_IN_TRANSFORMERS: Dict[Any, Transformer] = { diff --git a/discord/client.py b/discord/client.py index daf2b8855..68422435b 100644 --- a/discord/client.py +++ b/discord/client.py @@ -2550,7 +2550,7 @@ class Client: ) return Invite.from_incomplete(state=self._connection, data=data) - async def delete_invite(self, invite: Union[Invite, str], /) -> None: + async def delete_invite(self, invite: Union[Invite, str], /) -> Invite: """|coro| Revokes an :class:`.Invite`, URL, or ID to an invite. @@ -2578,7 +2578,8 @@ class Client: """ resolved = utils.resolve_invite(invite) - await self.http.delete_invite(resolved.code) + data = await self.http.delete_invite(resolved.code) + return Invite.from_incomplete(state=self._connection, data=data) # Miscellaneous stuff diff --git a/discord/embeds.py b/discord/embeds.py index 6bd057ac8..f55c7cac1 100644 --- a/discord/embeds.py +++ b/discord/embeds.py @@ -743,7 +743,7 @@ class Embed: # fmt: off result = { key[1:]: getattr(self, key) - for key in self.__slots__ + for key in Embed.__slots__ if key[0] == '_' and hasattr(self, key) } # fmt: on diff --git a/discord/ext/commands/parameters.py b/discord/ext/commands/parameters.py index 196530d94..2640902a3 100644 --- a/discord/ext/commands/parameters.py +++ b/discord/ext/commands/parameters.py @@ -109,6 +109,9 @@ class Parameter(inspect.Parameter): self._fallback = False self._displayed_name = displayed_name + def __repr__(self) -> str: + return f'<{self.__class__.__name__} name={self._name!r} required={self.required}>' + def replace( self, *, diff --git a/discord/guild.py b/discord/guild.py index 291363b18..2e834f9b2 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -1800,6 +1800,7 @@ class Guild(Hashable): category: Optional[CategoryChannel] = None, slowmode_delay: int = MISSING, nsfw: bool = MISSING, + media: bool = MISSING, overwrites: Mapping[Union[Role, Member, Object], PermissionOverwrite] = MISSING, reason: Optional[str] = None, default_auto_archive_duration: int = MISSING, @@ -1862,12 +1863,17 @@ class Guild(Hashable): .. versionadded:: 2.3 default_layout: :class:`ForumLayoutType` The default layout for posts in this forum. + This cannot be set if ``media`` is set to ``True``. .. versionadded:: 2.3 available_tags: Sequence[:class:`ForumTag`] The available tags for this forum channel. .. versionadded:: 2.1 + media: :class:`bool` + Whether to create a media forum channel. + + .. versionadded:: 2.6 Raises ------- @@ -1919,7 +1925,7 @@ class Guild(Hashable): else: raise ValueError(f'default_reaction_emoji parameter must be either Emoji, PartialEmoji, or str') - if default_layout is not MISSING: + if not media and default_layout is not MISSING: if not isinstance(default_layout, ForumLayoutType): raise TypeError( f'default_layout parameter must be a ForumLayoutType not {default_layout.__class__.__name__}' @@ -1931,10 +1937,17 @@ class Guild(Hashable): options['available_tags'] = [t.to_dict() for t in available_tags] data = await self._create_channel( - name=name, overwrites=overwrites, channel_type=ChannelType.forum, category=category, reason=reason, **options + name=name, + overwrites=overwrites, + channel_type=ChannelType.forum if not media else ChannelType.media, + category=category, + reason=reason, + **options, ) - channel = ForumChannel(state=self._state, guild=self, data=data) + channel = ForumChannel( + state=self._state, guild=self, data=data # pyright: ignore[reportArgumentType] # it's the correct data + ) # temporarily add to the cache self._channels[channel.id] = channel diff --git a/discord/http.py b/discord/http.py index ec616b36d..a907bbcd8 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1890,7 +1890,7 @@ class HTTPClient: def invites_from_channel(self, channel_id: Snowflake) -> Response[List[invite.Invite]]: return self.request(Route('GET', '/channels/{channel_id}/invites', channel_id=channel_id)) - def delete_invite(self, invite_id: str, *, reason: Optional[str] = None) -> Response[None]: + def delete_invite(self, invite_id: str, *, reason: Optional[str] = None) -> Response[invite.Invite]: return self.request(Route('DELETE', '/invites/{invite_id}', invite_id=invite_id), reason=reason) # Role management diff --git a/discord/interactions.py b/discord/interactions.py index cb9a21e88..abe47efa2 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -712,6 +712,9 @@ class InteractionCallbackResponse(Generic[ClientT]): self.type: InteractionResponseType = type self._update(data) + def __repr__(self) -> str: + return f'' + def _update(self, data: InteractionCallbackPayload) -> None: interaction = data['interaction'] diff --git a/discord/invite.py b/discord/invite.py index dd8cc954a..8c37bd232 100644 --- a/discord/invite.py +++ b/discord/invite.py @@ -546,7 +546,7 @@ class Invite(Hashable): return self - async def delete(self, *, reason: Optional[str] = None) -> None: + async def delete(self, *, reason: Optional[str] = None) -> Self: """|coro| Revokes the instant invite. @@ -568,4 +568,5 @@ class Invite(Hashable): Revoking the invite failed. """ - await self._state.http.delete_invite(self.code, reason=reason) + data = await self._state.http.delete_invite(self.code, reason=reason) + return self.from_incomplete(state=self._state, data=data) diff --git a/discord/message.py b/discord/message.py index 6fbdecbfc..ee6cfd4c2 100644 --- a/discord/message.py +++ b/discord/message.py @@ -989,6 +989,9 @@ class MessageApplication: self._icon: Optional[str] = data['icon'] self._cover_image: Optional[str] = data.get('cover_image') + def __str__(self) -> str: + return self.name + def __repr__(self) -> str: return f''