diff --git a/CHANGELOG.md b/CHANGELOG.md index 2225c67d10..a4ad23eb0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ These changes are available on the `master` branch, but have not yet been releas ([#2711](https://github.com/Pycord-Development/pycord/pull/2711)) - Added `RawMessageUpdateEvent.new_message` - message update events now contain full message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780)) +- Added support for setting guild-specific `avatar`, `banner`, and `bio` for the bot + user through `Member.edit`. + ([#2908](https://github.com/Pycord-Development/pycord/pull/2908)) ### Changed diff --git a/discord/http.py b/discord/http.py index 76e680f638..bfefed91d1 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1020,38 +1020,6 @@ def guild_voice_state( def edit_profile(self, payload: dict[str, Any]) -> Response[user.User]: return self.request(Route("PATCH", "/users/@me"), json=payload) - def change_my_nickname( - self, - guild_id: Snowflake, - nickname: str, - *, - reason: str | None = None, - ) -> Response[member.Nickname]: - r = Route("PATCH", "/guilds/{guild_id}/members/@me", guild_id=guild_id) - payload = { - "nick": nickname, - } - return self.request(r, json=payload, reason=reason) - - def change_nickname( - self, - guild_id: Snowflake, - user_id: Snowflake, - nickname: str, - *, - reason: str | None = None, - ) -> Response[member.Member]: - r = Route( - "PATCH", - "/guilds/{guild_id}/members/{user_id}", - guild_id=guild_id, - user_id=user_id, - ) - payload = { - "nick": nickname, - } - return self.request(r, json=payload, reason=reason) - def edit_my_voice_state( self, guild_id: Snowflake, payload: dict[str, Any] ) -> Response[None]: diff --git a/discord/member.py b/discord/member.py index 0ff90cce04..8d8e5bd818 100644 --- a/discord/member.py +++ b/discord/member.py @@ -39,6 +39,7 @@ from .asset import Asset from .colour import Colour from .enums import Status, try_enum +from .errors import InvalidArgument from .flags import MemberFlags from .object import Object from .permissions import Permissions @@ -769,6 +770,9 @@ async def edit( reason: str | None = None, communication_disabled_until: datetime.datetime | None = MISSING, bypass_verification: bool | None = MISSING, + banner: bytes | None = MISSING, + avatar: bytes | None = MISSING, + bio: str | None = MISSING, ) -> Member | None: """|coro| @@ -804,6 +808,14 @@ async def edit( - Client has ALL THREE of :attr:`Permissions.moderate_members`, :attr:`Permissions.kick_members`, and :attr:`Permissions.ban_members` + .. note:: + + The following parameters are only available when editing the bot's own member: + + - ``avatar`` + - ``banner`` + - ``bio`` + All parameters are optional. .. versionchanged:: 1.1 @@ -841,6 +853,26 @@ async def edit( Indicates if the member should bypass the guild's verification requirements. .. versionadded:: 2.6 + banner: Optional[:class:`bytes`] + A :term:`py:bytes-like object` representing the banner. + Could be ``None`` to denote removal of the banner. + + This is only available when editing the bot's own member (i.e. :attr:`Guild.me`). + + .. versionadded:: 2.7 + avatar: Optional[:class:`bytes`] + A :term:`py:bytes-like object` representing the avatar. + Could be ``None`` to denote removal of the avatar. + + This is only available when editing the bot's own member (i.e. :attr:`Guild.me`). + + .. versionadded:: 2.7 + bio: Optional[:class:`str`] + The new bio for the member. Could be ``None`` to denote removal of the bio. + + This is only available when editing the bot's own member (i.e. :attr:`Guild.me`). + + .. versionadded:: 2.7 Returns ------- @@ -854,16 +886,19 @@ async def edit( You do not have the proper permissions to the action requested. HTTPException The operation failed. + InvalidArgument + You tried to edit the avatar, banner, or bio of a member that is not the bot. """ http = self._state.http guild_id = self.guild.id me = self._state.self_id == self.id payload: dict[str, Any] = {} + bot_payload: dict[str, Any] = {} if nick is not MISSING: nick = nick or "" if me: - await http.change_my_nickname(guild_id, nick, reason=reason) + bot_payload["nick"] = nick else: payload["nick"] = nick @@ -910,9 +945,34 @@ async def edit( flags.bypasses_verification = bypass_verification payload["flags"] = flags.value + if avatar is not MISSING: + if avatar is None: + bot_payload["avatar"] = None + else: + bot_payload["avatar"] = utils._bytes_to_base64_data(avatar) + + if banner is not MISSING: + if banner is None: + bot_payload["banner"] = None + else: + bot_payload["banner"] = utils._bytes_to_base64_data(banner) + + if bio is not MISSING: + bot_payload["bio"] = bio or "" + + if bot_payload and not me: + raise InvalidArgument( + "Can only edit avatar, banner, or bio for the bot's member." + ) + if payload: data = await http.edit_member(guild_id, self.id, reason=reason, **payload) - return Member(data=data, guild=self.guild, state=self._state) + elif bot_payload: + data = await http.edit_member(guild_id, "@me", reason=reason, **bot_payload) + else: + return None + + return Member(data=data, guild=self.guild, state=self._state) async def timeout( self, until: datetime.datetime | None, *, reason: str | None = None