Browse Source

Initial support for pomelo migration

pull/10109/head
Rapptz 2 years ago
committed by dolfies
parent
commit
e6e380f904
  1. 7
      discord/abc.py
  2. 13
      discord/application.py
  3. 11
      discord/client.py
  4. 2
      discord/ext/commands/context.py
  5. 36
      discord/ext/commands/converter.py
  6. 24
      discord/guild.py
  7. 8
      discord/http.py
  8. 13
      discord/member.py
  9. 1
      discord/state.py
  10. 15
      discord/team.py
  11. 1
      discord/types/user.py
  12. 56
      discord/user.py
  13. 16
      discord/widget.py

7
discord/abc.py

@ -449,7 +449,9 @@ class User(Snowflake, Protocol):
name: :class:`str` name: :class:`str`
The user's username. The user's username.
discriminator: :class:`str` discriminator: :class:`str`
The user's discriminator. The user's discriminator. This is a legacy concept that is no longer used.
global_name: Optional[:class:`str`]
The user's global nickname.
bot: :class:`bool` bot: :class:`bool`
If the user is a bot account. If the user is a bot account.
system: :class:`bool` system: :class:`bool`
@ -458,6 +460,7 @@ class User(Snowflake, Protocol):
name: str name: str
discriminator: str discriminator: str
global_name: Optional[str]
bot: bool bot: bool
system: bool system: bool
@ -486,7 +489,7 @@ class User(Snowflake, Protocol):
@property @property
def default_avatar(self) -> Asset: def default_avatar(self) -> Asset:
""":class:`~discord.Asset`: Returns the default avatar for a given user. This is calculated by the user's discriminator.""" """:class:`~discord.Asset`: Returns the default avatar for a given user."""
raise NotImplementedError raise NotImplementedError
@property @property

13
discord/application.py

@ -2542,10 +2542,13 @@ class Application(PartialApplication):
# Passing a user object: # Passing a user object:
await app.whitelist(user) await app.whitelist(user)
# Passing a stringified user: # Passing a username
await app.whitelist('jake')
# Passing a legacy user:
await app.whitelist('Jake#0001') await app.whitelist('Jake#0001')
# Passing a username and discriminator: # Passing a legacy username and discriminator:
await app.whitelist('Jake', '0001') await app.whitelist('Jake', '0001')
Parameters Parameters
@ -2575,14 +2578,14 @@ class Application(PartialApplication):
user = args[0] user = args[0]
if isinstance(user, _UserTag): if isinstance(user, _UserTag):
user = str(user) user = str(user)
username, discrim = user.split('#') username, _, discrim = user.partition('#')
elif len(args) == 2: elif len(args) == 2:
username, discrim = args # type: ignore username, discrim = args # type: ignore
else: else:
raise TypeError(f'invite_member() takes 1 or 2 arguments but {len(args)} were given') raise TypeError(f'whitelist() takes 1 or 2 arguments but {len(args)} were given')
state = self._state state = self._state
data = await state.http.invite_team_member(self.id, username, discrim) data = await state.http.add_app_whitelist(self.id, username, discrim or 0)
return ApplicationTester(self, state, data) return ApplicationTester(self, state, data)
async def create_asset( async def create_asset(

11
discord/client.py

@ -2966,10 +2966,13 @@ class Client:
# Passing a user object: # Passing a user object:
await client.send_friend_request(user) await client.send_friend_request(user)
# Passing a stringified user: # Passing a username
await client.send_friend_request('jake')
# Passing a legacy user:
await client.send_friend_request('Jake#0001') await client.send_friend_request('Jake#0001')
# Passing a username and discriminator: # Passing a legacy username and discriminator:
await client.send_friend_request('Jake', '0001') await client.send_friend_request('Jake', '0001')
Parameters Parameters
@ -2996,14 +2999,14 @@ class Client:
user = args[0] user = args[0]
if isinstance(user, _UserTag): if isinstance(user, _UserTag):
user = str(user) user = str(user)
username, discrim = user.split('#') username, _, discrim = user.partition('#')
elif len(args) == 2: elif len(args) == 2:
username, discrim = args # type: ignore username, discrim = args # type: ignore
else: else:
raise TypeError(f'send_friend_request() takes 1 or 2 arguments but {len(args)} were given') raise TypeError(f'send_friend_request() takes 1 or 2 arguments but {len(args)} were given')
state = self._connection state = self._connection
await state.http.send_friend_request(username, discrim) await state.http.send_friend_request(username, discrim or 0)
async def applications(self, *, with_team_applications: bool = True) -> List[Application]: async def applications(self, *, with_team_applications: bool = True) -> List[Application]:
"""|coro| """|coro|

2
discord/ext/commands/context.py

@ -311,7 +311,7 @@ class Context(discord.abc.Messageable, Generic[BotT]):
def filesize_limit(self) -> int: def filesize_limit(self) -> int:
""":class:`int`: Returns the maximum number of bytes files can have when uploaded to this guild or DM channel associated with this context. """:class:`int`: Returns the maximum number of bytes files can have when uploaded to this guild or DM channel associated with this context.
.. versionadded:: 2.3 .. versionadded:: 2.1
""" """
return self.guild.filesize_limit if self.guild is not None else 26214400 return self.guild.filesize_limit if self.guild is not None else 26214400

36
discord/ext/commands/converter.py

@ -186,9 +186,9 @@ class MemberConverter(IDConverter[discord.Member]):
1. Lookup by ID. 1. Lookup by ID.
2. Lookup by mention. 2. Lookup by mention.
3. Lookup by name#discrim 3. Lookup by guild nickname
4. Lookup by name 4. Lookup by global name
5. Lookup by nickname 5. Lookup by user name
.. versionchanged:: 1.5 .. versionchanged:: 1.5
Raise :exc:`.MemberNotFound` instead of generic :exc:`.BadArgument` Raise :exc:`.MemberNotFound` instead of generic :exc:`.BadArgument`
@ -196,17 +196,15 @@ class MemberConverter(IDConverter[discord.Member]):
.. versionchanged:: 1.5.1 .. versionchanged:: 1.5.1
This converter now lazily fetches members from the gateway and HTTP APIs, This converter now lazily fetches members from the gateway and HTTP APIs,
optionally caching the result if :attr:`.MemberCacheFlags.joined` is enabled. optionally caching the result if :attr:`.MemberCacheFlags.joined` is enabled.
.. versionchanged:: 2.1
This converter lookup strategy has changed due to the removal of discriminators.
""" """
async def query_member_named(self, guild: discord.Guild, argument: str) -> Optional[discord.Member]: async def query_member_named(self, guild: discord.Guild, argument: str) -> Optional[discord.Member]:
cache = guild._state.member_cache_flags.joined cache = guild._state.member_cache_flags.joined
if len(argument) > 5 and argument[-5] == '#': members = await guild.query_members(argument, limit=100, cache=cache)
username, _, discriminator = argument.rpartition('#') return discord.utils.find(lambda m: m.nick == argument or m.global_name == argument or m.name == argument, members)
members = await guild.query_members(username, limit=100, cache=cache)
return discord.utils.get(members, name=username, discriminator=discriminator)
else:
members = await guild.query_members(argument, limit=100, cache=cache)
return discord.utils.find(lambda m: m.name == argument or m.nick == argument, members)
async def query_member_by_id(self, bot, guild, user_id): async def query_member_by_id(self, bot, guild, user_id):
ws = bot.ws ws = bot.ws
@ -273,8 +271,8 @@ class UserConverter(IDConverter[discord.User]):
1. Lookup by ID. 1. Lookup by ID.
2. Lookup by mention. 2. Lookup by mention.
3. Lookup by name#discrim 3. Lookup by global name
4. Lookup by name 4. Lookup by user name
.. versionchanged:: 1.5 .. versionchanged:: 1.5
Raise :exc:`.UserNotFound` instead of generic :exc:`.BadArgument` Raise :exc:`.UserNotFound` instead of generic :exc:`.BadArgument`
@ -282,6 +280,9 @@ class UserConverter(IDConverter[discord.User]):
.. versionchanged:: 1.6 .. versionchanged:: 1.6
This converter now lazily fetches users from the HTTP APIs if an ID is passed This converter now lazily fetches users from the HTTP APIs if an ID is passed
and it's not available in cache. and it's not available in cache.
.. versionchanged:: 2.1
This converter lookup strategy has changed due to the removal of discriminators.
""" """
async def convert(self, ctx: Context[BotT], argument: str) -> discord.User: async def convert(self, ctx: Context[BotT], argument: str) -> discord.User:
@ -307,16 +308,7 @@ class UserConverter(IDConverter[discord.User]):
# Remove first character # Remove first character
arg = arg[1:] arg = arg[1:]
# check for discriminator if it exists, predicate = lambda u: u.global_name == arg or u.name == arg
if len(arg) > 5 and arg[-5] == '#':
discrim = arg[-4:]
name = arg[:-5]
predicate = lambda u: u.name == name and u.discriminator == discrim
result = discord.utils.find(predicate, state._users.values())
if result is not None:
return result
predicate = lambda u: u.name == arg
result = discord.utils.find(predicate, state._users.values()) result = discord.utils.find(predicate, state._users.values())
if result is None: if result is None:

24
discord/guild.py

@ -1298,26 +1298,20 @@ class Guild(Hashable):
def get_member_named(self, name: str, /) -> Optional[Member]: def get_member_named(self, name: str, /) -> Optional[Member]:
"""Returns the first member found that matches the name provided. """Returns the first member found that matches the name provided.
The name can have an optional discriminator argument, e.g. "Jake#0001"
or "Jake" will both do the lookup. However the former will give a more
precise result. Note that the discriminator must have all 4 digits
for this to work.
If a nickname is passed, then it is looked up via the nickname. Note
however, that a nickname + discriminator combo will not lookup the nickname
but rather the username + discriminator combo due to nickname + discriminator
not being unique.
If no member is found, ``None`` is returned. If no member is found, ``None`` is returned.
.. versionchanged:: 2.0 .. versionchanged:: 2.0
``name`` parameter is now positional-only. ``name`` parameter is now positional-only.
.. versionchanged:: 2.1
``discriminator`` is no longer used in lookup, due to being removed on Discord.
Parameters Parameters
----------- -----------
name: :class:`str` name: :class:`str`
The name of the member to lookup with an optional discriminator. The name of the member to lookup.
Returns Returns
-------- --------
@ -1328,14 +1322,8 @@ class Guild(Hashable):
members = self.members members = self.members
if len(name) > 5 and name[-5] == '#':
potential_discriminator = name[-4:]
result = utils.get(members, name=name[:-5], discriminator=potential_discriminator)
if result is not None:
return result
def pred(m: Member) -> bool: def pred(m: Member) -> bool:
return m.nick == name or m.name == name return m.nick == name or m.global_name == name or m.name == name
return utils.find(pred, members) return utils.find(pred, members)

8
discord/http.py

@ -2894,7 +2894,7 @@ class HTTPClient:
def send_friend_request(self, username: str, discriminator: Snowflake) -> Response[None]: def send_friend_request(self, username: str, discriminator: Snowflake) -> Response[None]:
r = Route('POST', '/users/@me/relationships') r = Route('POST', '/users/@me/relationships')
props = choice((ContextProperties.from_add_friend, ContextProperties.from_group_dm))() # Friends, Group DM props = choice((ContextProperties.from_add_friend, ContextProperties.from_group_dm))() # Friends, Group DM
payload = {'username': username, 'discriminator': int(discriminator)} payload = {'username': username, 'discriminator': int(discriminator) or None}
return self.request(r, json=payload, context_properties=props) return self.request(r, json=payload, context_properties=props)
@ -3180,9 +3180,9 @@ class HTTPClient:
) )
def add_app_whitelist( def add_app_whitelist(
self, app_id: Snowflake, username: str, discriminator: str self, app_id: Snowflake, username: str, discriminator: Snowflake
) -> Response[application.WhitelistedUser]: ) -> Response[application.WhitelistedUser]:
payload = {'username': username, 'discriminator': discriminator} payload = {'username': username, 'discriminator': str(discriminator) or None}
return self.request( return self.request(
Route('POST', '/oauth2/applications/{app_id}/allowlist', app_id=app_id), Route('POST', '/oauth2/applications/{app_id}/allowlist', app_id=app_id),
@ -3279,7 +3279,7 @@ class HTTPClient:
return self.request(Route('GET', '/teams/{team_id}/members', team_id=team_id), super_properties_to_track=True) return self.request(Route('GET', '/teams/{team_id}/members', team_id=team_id), super_properties_to_track=True)
def invite_team_member(self, team_id: Snowflake, username: str, discriminator: Snowflake): def invite_team_member(self, team_id: Snowflake, username: str, discriminator: Snowflake):
payload = {'username': username, 'discriminator': str(discriminator)} payload = {'username': username, 'discriminator': str(discriminator) or None}
return self.request( return self.request(
Route('POST', '/teams/{team_id}/members', team_id=team_id), json=payload, super_properties_to_track=True Route('POST', '/teams/{team_id}/members', team_id=team_id), json=payload, super_properties_to_track=True

13
discord/member.py

@ -243,7 +243,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
.. describe:: str(x) .. describe:: str(x)
Returns the member's name with the discriminator. Returns the member's name with a ``@``.
Attributes Attributes
---------- ----------
@ -253,7 +253,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
guild: :class:`Guild` guild: :class:`Guild`
The guild that the member belongs to. The guild that the member belongs to.
nick: Optional[:class:`str`] nick: Optional[:class:`str`]
The guild specific nickname of the user. The guild specific nickname of the user. Takes precedence over the global name.
pending: :class:`bool` pending: :class:`bool`
Whether the member is pending member verification. Whether the member is pending member verification.
@ -287,6 +287,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
name: str name: str
id: int id: int
discriminator: str discriminator: str
global_name: Optional[str]
bot: bool bot: bool
system: bool system: bool
created_at: datetime.datetime created_at: datetime.datetime
@ -328,7 +329,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return (
f'<Member id={self._user.id} name={self._user.name!r} discriminator={self._user.discriminator!r}' f'<Member id={self._user.id} name={self._user.name!r} global_name={self._user.global_name!r}'
f' bot={self._user.bot} nick={self.nick!r} guild={self.guild!r}>' f' bot={self._user.bot} nick={self.nick!r} guild={self.guild!r}>'
) )
@ -537,11 +538,11 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
def display_name(self) -> str: def display_name(self) -> str:
""":class:`str`: Returns the user's display name. """:class:`str`: Returns the user's display name.
For regular users this is just their username, but For regular users this is just their global name or their username,
if they have a guild specific nickname then that but if they have a guild specific nickname then that
is returned instead. is returned instead.
""" """
return self.nick or self.name return self.nick or self.global_name or self.name
@property @property
def display_avatar(self) -> Asset: def display_avatar(self) -> Asset:

1
discord/state.py

@ -755,6 +755,7 @@ class ConnectionState:
return self._users[user_id] return self._users[user_id]
except KeyError: except KeyError:
user = User(state=self, data=data) user = User(state=self, data=data)
# TODO: with the removal of discrims this becomes a bit annoying
if user.discriminator != '0000': if user.discriminator != '0000':
self._users[user_id] = user self._users[user_id] = user
return user return user

15
discord/team.py

@ -288,10 +288,13 @@ class Team(Hashable):
# Passing a user object: # Passing a user object:
await team.invite_member(user) await team.invite_member(user)
# Passing a stringified user: # Passing a username
await team.invite_member('jake')
# Passing a legacy user:
await team.invite_member('Jake#0001') await team.invite_member('Jake#0001')
# Passing a username and discriminator: # Passing a legacy username and discriminator:
await team.invite_member('Jake', '0001') await team.invite_member('Jake', '0001')
Parameters Parameters
@ -323,14 +326,14 @@ class Team(Hashable):
user = args[0] user = args[0]
if isinstance(user, _UserTag): if isinstance(user, _UserTag):
user = str(user) user = str(user)
username, discrim = user.split('#') username, _, discrim = user.partition('#')
elif len(args) == 2: elif len(args) == 2:
username, discrim = args # type: ignore username, discrim = args # type: ignore
else: else:
raise TypeError(f'invite_member() takes 1 or 2 arguments but {len(args)} were given') raise TypeError(f'invite_member() takes 1 or 2 arguments but {len(args)} were given')
state = self._state state = self._state
data = await state.http.invite_team_member(self.id, username, discrim) data = await state.http.invite_team_member(self.id, username, discrim or 0)
member = TeamMember(self, state, data) member = TeamMember(self, state, data)
self.members.append(member) self.members.append(member)
return member return member
@ -494,7 +497,7 @@ class TeamMember(User):
.. describe:: str(x) .. describe:: str(x)
Returns the team member's name with discriminator. Returns the team member's name with a ``@``.
.. versionadded:: 1.3 .. versionadded:: 1.3
@ -519,7 +522,7 @@ class TeamMember(User):
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return (
f'<{self.__class__.__name__} id={self.id} name={self.name!r} ' f'<{self.__class__.__name__} id={self.id} name={self.name!r} '
f'discriminator={self.discriminator!r} membership_state={self.membership_state!r}>' f'global_name={self.global_name!r} membership_state={self.membership_state!r}>'
) )
async def remove(self) -> None: async def remove(self) -> None:

1
discord/types/user.py

@ -38,6 +38,7 @@ class PartialUser(TypedDict):
public_flags: NotRequired[int] public_flags: NotRequired[int]
bot: NotRequired[bool] bot: NotRequired[bool]
system: NotRequired[bool] system: NotRequired[bool]
global_name: Optional[str]
ConnectionType = Literal[ ConnectionType = Literal[

56
discord/user.py

@ -58,6 +58,7 @@ if TYPE_CHECKING:
from .state import ConnectionState from .state import ConnectionState
from .types.channel import DMChannel as DMChannelPayload from .types.channel import DMChannel as DMChannelPayload
from .types.user import ( from .types.user import (
APIUser as APIUserPayload,
PartialUser as PartialUserPayload, PartialUser as PartialUserPayload,
User as UserPayload, User as UserPayload,
) )
@ -239,6 +240,7 @@ class BaseUser(_UserTag):
'name', 'name',
'id', 'id',
'discriminator', 'discriminator',
'global_name',
'_avatar', '_avatar',
'_avatar_decoration', '_avatar_decoration',
'_banner', '_banner',
@ -254,6 +256,7 @@ class BaseUser(_UserTag):
name: str name: str
id: int id: int
discriminator: str discriminator: str
global_name: Optional[str]
bot: bool bot: bool
system: bool system: bool
_state: ConnectionState _state: ConnectionState
@ -269,12 +272,12 @@ class BaseUser(_UserTag):
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return (
f"<BaseUser id={self.id} name={self.name!r} discriminator={self.discriminator!r}" f"<BaseUser id={self.id} name={self.name!r} global_name={self.global_name!r}"
f" bot={self.bot} system={self.system}>" f" bot={self.bot} system={self.system}>"
) )
def __str__(self) -> str: def __str__(self) -> str:
return f'{self.name}#{self.discriminator}' return f'@{self.name}'
def __eq__(self, other: object) -> bool: def __eq__(self, other: object) -> bool:
return isinstance(other, _UserTag) and other.id == self.id return isinstance(other, _UserTag) and other.id == self.id
@ -289,6 +292,7 @@ class BaseUser(_UserTag):
self.name = data['username'] self.name = data['username']
self.id = int(data['id']) self.id = int(data['id'])
self.discriminator = data['discriminator'] self.discriminator = data['discriminator']
self.global_name = data.get('global_name')
self._avatar = data['avatar'] self._avatar = data['avatar']
self._avatar_decoration = data.get('avatar_decoration') self._avatar_decoration = data.get('avatar_decoration')
self._banner = data.get('banner', None) self._banner = data.get('banner', None)
@ -304,6 +308,7 @@ class BaseUser(_UserTag):
self.name = user.name self.name = user.name
self.id = user.id self.id = user.id
self.discriminator = user.discriminator self.discriminator = user.discriminator
self.global_name = user.global_name
self._avatar = user._avatar self._avatar = user._avatar
self._avatar_decoration = user._avatar_decoration self._avatar_decoration = user._avatar_decoration
self._banner = user._banner self._banner = user._banner
@ -315,16 +320,19 @@ class BaseUser(_UserTag):
return self return self
def _to_minimal_user_json(self) -> PartialUserPayload: def _to_minimal_user_json(self) -> APIUserPayload:
user: PartialUserPayload = { user: APIUserPayload = {
'username': self.name, 'username': self.name,
'id': self.id, 'id': self.id,
'avatar': self._avatar, 'avatar': self._avatar,
'avatar_decoration': self._avatar_decoration, 'avatar_decoration': self._avatar_decoration,
'discriminator': self.discriminator, 'discriminator': self.discriminator,
'global_name': self.global_name,
'bot': self.bot, 'bot': self.bot,
'system': self.system, 'system': self.system,
'public_flags': self._public_flags, 'public_flags': self._public_flags,
'banner': self._banner,
'accent_color': self._accent_colour,
} }
return user return user
@ -351,8 +359,13 @@ class BaseUser(_UserTag):
@property @property
def default_avatar(self) -> Asset: def default_avatar(self) -> Asset:
""":class:`Asset`: Returns the default avatar for a given user. This is calculated by the user's discriminator.""" """:class:`Asset`: Returns the default avatar for a given user."""
return Asset._from_default_avatar(self._state, int(self.discriminator) % 5) if self.discriminator == '0':
avatar_id = self.id % 5
else:
avatar_id = int(self.discriminator) % 5
return Asset._from_default_avatar(self._state, avatar_id)
@property @property
def display_avatar(self) -> Asset: def display_avatar(self) -> Asset:
@ -470,10 +483,12 @@ class BaseUser(_UserTag):
def display_name(self) -> str: def display_name(self) -> str:
""":class:`str`: Returns the user's display name. """:class:`str`: Returns the user's display name.
For regular users this is just their username, but For regular users this is just their global name or their username,
if they have a guild specific nickname then that but if they have a guild specific nickname then that
is returned instead. is returned instead.
""" """
if self.global_name:
return self.global_name
return self.name return self.name
@cached_slot_property('_cs_note') @cached_slot_property('_cs_note')
@ -594,7 +609,7 @@ class ClientUser(BaseUser):
.. describe:: str(x) .. describe:: str(x)
Returns the user's name with discriminator. Returns the user's name with a ``@``.
.. versionchanged:: 2.0 .. versionchanged:: 2.0
:attr:`Locale` is now a :class:`Locale` instead of a Optional[:class:`str`]. :attr:`Locale` is now a :class:`Locale` instead of a Optional[:class:`str`].
@ -606,9 +621,13 @@ class ClientUser(BaseUser):
id: :class:`int` id: :class:`int`
The user's unique ID. The user's unique ID.
discriminator: :class:`str` discriminator: :class:`str`
The user's discriminator. The user's discriminator. This is a legacy concept that is no longer used.
bio: Optional[:class:`str`] bio: Optional[:class:`str`]
The user's "about me" field. Could be ``None``. The user's "about me" field. Could be ``None``.
global_name: Optional[:class:`str`]
The user's global nickname, taking precedence over the username in display.
.. versionadded:: 2.1
bot: :class:`bool` bot: :class:`bool`
Specifies if the user is a bot account. Specifies if the user is a bot account.
system: :class:`bool` system: :class:`bool`
@ -686,8 +705,8 @@ class ClientUser(BaseUser):
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return (
f'<ClientUser id={self.id} name={self.name!r} discriminator={self.discriminator!r}' f'<ClientUser id={self.id} name={self.name!r} global_name={self.global_name!r}'
f' bot={self.bot} verified={self.verified} mfa_enabled={self.mfa_enabled} premium={self.premium}>' f' verified={self.verified} mfa_enabled={self.mfa_enabled} premium={self.premium}>'
) )
def _full_update(self, data: UserPayload) -> None: def _full_update(self, data: UserPayload) -> None:
@ -928,7 +947,7 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
.. describe:: str(x) .. describe:: str(x)
Returns the user's name with discriminator. Returns the user's name with a ``@``.
Attributes Attributes
----------- -----------
@ -937,7 +956,11 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
id: :class:`int` id: :class:`int`
The user's unique ID. The user's unique ID.
discriminator: :class:`str` discriminator: :class:`str`
The user's discriminator. The user's discriminator. This is a legacy concept that is no longer used.
global_name: Optional[:class:`str`]
The user's global nickname, taking precedence over the username in display.
.. versionadded:: 2.1
bot: :class:`bool` bot: :class:`bool`
Specifies if the user is a bot account. Specifies if the user is a bot account.
system: :class:`bool` system: :class:`bool`
@ -947,7 +970,7 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
__slots__ = ('__weakref__',) __slots__ = ('__weakref__',)
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name!r} discriminator={self.discriminator!r} bot={self.bot} system={self.system}>' return f'<User id={self.id} name={self.name!r} global_name={self.global_name!r} bot={self.bot}>'
def _get_voice_client_key(self) -> Tuple[int, str]: def _get_voice_client_key(self) -> Tuple[int, str]:
return self._state.self_id, 'self_id' # type: ignore # self_id is always set at this point return self._state.self_id, 'self_id' # type: ignore # self_id is always set at this point
@ -967,10 +990,11 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
user['discriminator'], user['discriminator'],
user.get('public_flags', 0), user.get('public_flags', 0),
user.get('avatar_decoration'), user.get('avatar_decoration'),
user.get('global_name')
) )
if original != modified: if original != modified:
to_return = User._copy(self) to_return = User._copy(self)
self.name, self._avatar, self.discriminator, self._public_flags, self._avatar_decoration = modified self.name, self._avatar, self.discriminator, self._public_flags, self._avatar_decoration, self.global_name = modified
# Signal to dispatch user_update # Signal to dispatch user_update
return to_return, self return to_return, self

16
discord/widget.py

@ -121,7 +121,7 @@ class WidgetMember(BaseUser):
.. describe:: str(x) .. describe:: str(x)
Returns the widget member's ``name#discriminator``. Returns the widget member's name with a ``@``.
Attributes Attributes
----------- -----------
@ -130,13 +130,19 @@ class WidgetMember(BaseUser):
name: :class:`str` name: :class:`str`
The member's username. The member's username.
discriminator: :class:`str` discriminator: :class:`str`
The member's discriminator. The member's discriminator. This is a legacy concept that is no longer used.
global_name: Optional[:class:`str`]
The member's global nickname, taking precedence over the username in display.
.. versionadded:: 2.1
bot: :class:`bool` bot: :class:`bool`
Whether the member is a bot. Whether the member is a bot.
status: :class:`Status` status: :class:`Status`
The member's status. The member's status.
nick: Optional[:class:`str`] nick: Optional[:class:`str`]
The member's nickname. The member's guild-specific nickname. Takes precedence over the global name.
avatar: Optional[:class:`str`]
The member's avatar hash.
activity: Optional[Union[:class:`BaseActivity`, :class:`Spotify`]] activity: Optional[Union[:class:`BaseActivity`, :class:`Spotify`]]
The member's activity. The member's activity.
deafened: Optional[:class:`bool`] deafened: Optional[:class:`bool`]
@ -189,9 +195,7 @@ class WidgetMember(BaseUser):
self.connected_channel: Optional[WidgetChannel] = connected_channel self.connected_channel: Optional[WidgetChannel] = connected_channel
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return f"<WidgetMember name={self.name!r} global_name={self.global_name!r} bot={self.bot} nick={self.nick!r}>"
f"<WidgetMember name={self.name!r} discriminator={self.discriminator!r}" f" bot={self.bot} nick={self.nick!r}>"
)
@property @property
def display_name(self) -> str: def display_name(self) -> str:

Loading…
Cancel
Save