Skip to content

Commit c461cbf

Browse files
authored
Merge branch 'master' into feat/voice-rewrite-and-fixes
2 parents 79e926c + 907931d commit c461cbf

File tree

5 files changed

+91
-52
lines changed

5 files changed

+91
-52
lines changed

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
blank_issues_enabled: false
1+
blank_issues_enabled: true
22
contact_links:
33
- name: Ask a question
44
about: Ask questions and discuss with other users of the library.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ 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 support for setting guild-specific `avatar`, `banner`, and `bio` for the bot
21+
user through `Member.edit`.
22+
([#2908](https://github.com/Pycord-Development/pycord/pull/2908))
2023

2124
### Changed
2225

@@ -28,6 +31,8 @@ These changes are available on the `master` branch, but have not yet been releas
2831
([#2905](https://github.com/Pycord-Development/pycord/pull/2905))
2932
- `view=None` in various methods causing an AttributeError.
3033
([#2915](https://github.com/Pycord-Development/pycord/pull/2915))
34+
- `View.message` being `None` when it had not been interacted with yet.
35+
([#2916](https://github.com/Pycord-Development/pycord/pull/2916))
3136

3237
### Removed
3338

discord/http.py

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,38 +1020,6 @@ def guild_voice_state(
10201020
def edit_profile(self, payload: dict[str, Any]) -> Response[user.User]:
10211021
return self.request(Route("PATCH", "/users/@me"), json=payload)
10221022

1023-
def change_my_nickname(
1024-
self,
1025-
guild_id: Snowflake,
1026-
nickname: str,
1027-
*,
1028-
reason: str | None = None,
1029-
) -> Response[member.Nickname]:
1030-
r = Route("PATCH", "/guilds/{guild_id}/members/@me", guild_id=guild_id)
1031-
payload = {
1032-
"nick": nickname,
1033-
}
1034-
return self.request(r, json=payload, reason=reason)
1035-
1036-
def change_nickname(
1037-
self,
1038-
guild_id: Snowflake,
1039-
user_id: Snowflake,
1040-
nickname: str,
1041-
*,
1042-
reason: str | None = None,
1043-
) -> Response[member.Member]:
1044-
r = Route(
1045-
"PATCH",
1046-
"/guilds/{guild_id}/members/{user_id}",
1047-
guild_id=guild_id,
1048-
user_id=user_id,
1049-
)
1050-
payload = {
1051-
"nick": nickname,
1052-
}
1053-
return self.request(r, json=payload, reason=reason)
1054-
10551023
def edit_my_voice_state(
10561024
self, guild_id: Snowflake, payload: dict[str, Any]
10571025
) -> Response[None]:

discord/interactions.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -613,11 +613,13 @@ async def edit_original_response(
613613
# The message channel types should always match
614614
state = _InteractionMessageState(self, self._state)
615615
message = InteractionMessage(state=state, channel=self.channel, data=data) # type: ignore
616-
if view and not view.is_finished():
616+
if view:
617+
if not view.is_finished():
618+
view.refresh(message.components)
619+
if view.is_dispatchable():
620+
self._state.store_view(view, message.id)
621+
617622
view.message = message
618-
view.refresh(message.components)
619-
if view.is_dispatchable():
620-
self._state.store_view(view, message.id)
621623

622624
if delete_after is not None:
623625
await self.delete_original_response(delay=delete_after)
@@ -1030,7 +1032,7 @@ async def send_message(
10301032

10311033
flags = MessageFlags(ephemeral=ephemeral)
10321034

1033-
if view is not None:
1035+
if view:
10341036
payload["components"] = view.to_components()
10351037
if view.is_components_v2():
10361038
if embeds or content:
@@ -1100,16 +1102,19 @@ async def send_message(
11001102
for file in files:
11011103
file.close()
11021104

1103-
if view is not None:
1104-
if ephemeral and view.timeout is None:
1105-
view.timeout = 15 * 60.0
1106-
1107-
view.parent = self._parent
1108-
if view.is_dispatchable():
1109-
self._parent._state.store_view(view)
1110-
11111105
self._responded = True
11121106
await self._process_callback_response(callback_response)
1107+
if view:
1108+
if not view.is_finished():
1109+
if ephemeral and view.timeout is None:
1110+
view.timeout = 15 * 60.0
1111+
1112+
view.parent = self._parent
1113+
if view.is_dispatchable():
1114+
self._parent._state.store_view(view)
1115+
1116+
view.message = await self._parent.original_response()
1117+
11131118
if delete_after is not None:
11141119
await self._parent.delete_original_response(delay=delete_after)
11151120
return self._parent
@@ -1268,12 +1273,13 @@ async def edit_message(
12681273
for file in files:
12691274
file.close()
12701275

1271-
if view and not view.is_finished():
1272-
view.message = msg
1273-
state.store_view(view, message_id)
1274-
12751276
self._responded = True
12761277
await self._process_callback_response(callback_response)
1278+
if view:
1279+
if not view.is_finished():
1280+
state.store_view(view, message_id)
1281+
view.message = msg or await parent.original_response()
1282+
12771283
if delete_after is not None:
12781284
await self._parent.delete_original_response(delay=delete_after)
12791285

discord/member.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from .asset import Asset
4040
from .colour import Colour
4141
from .enums import Status, try_enum
42+
from .errors import InvalidArgument
4243
from .flags import MemberFlags
4344
from .object import Object
4445
from .permissions import Permissions
@@ -782,6 +783,9 @@ async def edit(
782783
reason: str | None = None,
783784
communication_disabled_until: datetime.datetime | None = MISSING,
784785
bypass_verification: bool | None = MISSING,
786+
banner: bytes | None = MISSING,
787+
avatar: bytes | None = MISSING,
788+
bio: str | None = MISSING,
785789
) -> Member | None:
786790
"""|coro|
787791
@@ -817,6 +821,14 @@ async def edit(
817821
818822
- Client has ALL THREE of :attr:`Permissions.moderate_members`, :attr:`Permissions.kick_members`, and :attr:`Permissions.ban_members`
819823
824+
.. note::
825+
826+
The following parameters are only available when editing the bot's own member:
827+
828+
- ``avatar``
829+
- ``banner``
830+
- ``bio``
831+
820832
All parameters are optional.
821833
822834
.. versionchanged:: 1.1
@@ -854,6 +866,26 @@ async def edit(
854866
Indicates if the member should bypass the guild's verification requirements.
855867
856868
.. versionadded:: 2.6
869+
banner: Optional[:class:`bytes`]
870+
A :term:`py:bytes-like object` representing the banner.
871+
Could be ``None`` to denote removal of the banner.
872+
873+
This is only available when editing the bot's own member (i.e. :attr:`Guild.me`).
874+
875+
.. versionadded:: 2.7
876+
avatar: Optional[:class:`bytes`]
877+
A :term:`py:bytes-like object` representing the avatar.
878+
Could be ``None`` to denote removal of the avatar.
879+
880+
This is only available when editing the bot's own member (i.e. :attr:`Guild.me`).
881+
882+
.. versionadded:: 2.7
883+
bio: Optional[:class:`str`]
884+
The new bio for the member. Could be ``None`` to denote removal of the bio.
885+
886+
This is only available when editing the bot's own member (i.e. :attr:`Guild.me`).
887+
888+
.. versionadded:: 2.7
857889
858890
Returns
859891
-------
@@ -867,16 +899,19 @@ async def edit(
867899
You do not have the proper permissions to the action requested.
868900
HTTPException
869901
The operation failed.
902+
InvalidArgument
903+
You tried to edit the avatar, banner, or bio of a member that is not the bot.
870904
"""
871905
http = self._state.http
872906
guild_id = self.guild.id
873907
me = self._state.self_id == self.id
874908
payload: dict[str, Any] = {}
909+
bot_payload: dict[str, Any] = {}
875910

876911
if nick is not MISSING:
877912
nick = nick or ""
878913
if me:
879-
await http.change_my_nickname(guild_id, nick, reason=reason)
914+
bot_payload["nick"] = nick
880915
else:
881916
payload["nick"] = nick
882917

@@ -923,9 +958,34 @@ async def edit(
923958
flags.bypasses_verification = bypass_verification
924959
payload["flags"] = flags.value
925960

961+
if avatar is not MISSING:
962+
if avatar is None:
963+
bot_payload["avatar"] = None
964+
else:
965+
bot_payload["avatar"] = utils._bytes_to_base64_data(avatar)
966+
967+
if banner is not MISSING:
968+
if banner is None:
969+
bot_payload["banner"] = None
970+
else:
971+
bot_payload["banner"] = utils._bytes_to_base64_data(banner)
972+
973+
if bio is not MISSING:
974+
bot_payload["bio"] = bio or ""
975+
976+
if bot_payload and not me:
977+
raise InvalidArgument(
978+
"Can only edit avatar, banner, or bio for the bot's member."
979+
)
980+
926981
if payload:
927982
data = await http.edit_member(guild_id, self.id, reason=reason, **payload)
928-
return Member(data=data, guild=self.guild, state=self._state)
983+
elif bot_payload:
984+
data = await http.edit_member(guild_id, "@me", reason=reason, **bot_payload)
985+
else:
986+
return None
987+
988+
return Member(data=data, guild=self.guild, state=self._state)
929989

930990
async def timeout(
931991
self, until: datetime.datetime | None, *, reason: str | None = None

0 commit comments

Comments
 (0)