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`
The user's username.
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`
If the user is a bot account.
system: :class:`bool`
@ -458,6 +460,7 @@ class User(Snowflake, Protocol):
name: str
discriminator: str
global_name: Optional[str]
bot: bool
system: bool
@ -486,7 +489,7 @@ class User(Snowflake, Protocol):
@property
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
@property

13
discord/application.py

@ -2542,10 +2542,13 @@ class Application(PartialApplication):
# Passing a user object:
await app.whitelist(user)
# Passing a stringified user:
# Passing a username
await app.whitelist('jake')
# Passing a legacy user:
await app.whitelist('Jake#0001')
# Passing a username and discriminator:
# Passing a legacy username and discriminator:
await app.whitelist('Jake', '0001')
Parameters
@ -2575,14 +2578,14 @@ class Application(PartialApplication):
user = args[0]
if isinstance(user, _UserTag):
user = str(user)
username, discrim = user.split('#')
username, _, discrim = user.partition('#')
elif len(args) == 2:
username, discrim = args # type: ignore
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
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)
async def create_asset(

11
discord/client.py

@ -2966,10 +2966,13 @@ class Client:
# Passing a user object:
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')
# Passing a username and discriminator:
# Passing a legacy username and discriminator:
await client.send_friend_request('Jake', '0001')
Parameters
@ -2996,14 +2999,14 @@ class Client:
user = args[0]
if isinstance(user, _UserTag):
user = str(user)
username, discrim = user.split('#')
username, _, discrim = user.partition('#')
elif len(args) == 2:
username, discrim = args # type: ignore
else:
raise TypeError(f'send_friend_request() takes 1 or 2 arguments but {len(args)} were given')
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]:
"""|coro|

2
discord/ext/commands/context.py

@ -311,7 +311,7 @@ class Context(discord.abc.Messageable, Generic[BotT]):
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.
.. versionadded:: 2.3
.. versionadded:: 2.1
"""
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.
2. Lookup by mention.
3. Lookup by name#discrim
4. Lookup by name
5. Lookup by nickname
3. Lookup by guild nickname
4. Lookup by global name
5. Lookup by user name
.. versionchanged:: 1.5
Raise :exc:`.MemberNotFound` instead of generic :exc:`.BadArgument`
@ -196,17 +196,15 @@ class MemberConverter(IDConverter[discord.Member]):
.. versionchanged:: 1.5.1
This converter now lazily fetches members from the gateway and HTTP APIs,
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]:
cache = guild._state.member_cache_flags.joined
if len(argument) > 5 and argument[-5] == '#':
username, _, discriminator = argument.rpartition('#')
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)
members = await guild.query_members(argument, limit=100, cache=cache)
return discord.utils.find(lambda m: m.nick == argument or m.global_name == argument or m.name == argument, members)
async def query_member_by_id(self, bot, guild, user_id):
ws = bot.ws
@ -273,8 +271,8 @@ class UserConverter(IDConverter[discord.User]):
1. Lookup by ID.
2. Lookup by mention.
3. Lookup by name#discrim
4. Lookup by name
3. Lookup by global name
4. Lookup by user name
.. versionchanged:: 1.5
Raise :exc:`.UserNotFound` instead of generic :exc:`.BadArgument`
@ -282,6 +280,9 @@ class UserConverter(IDConverter[discord.User]):
.. versionchanged:: 1.6
This converter now lazily fetches users from the HTTP APIs if an ID is passed
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:
@ -307,16 +308,7 @@ class UserConverter(IDConverter[discord.User]):
# Remove first character
arg = arg[1:]
# check for discriminator if it exists,
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
predicate = lambda u: u.global_name == arg or u.name == arg
result = discord.utils.find(predicate, state._users.values())
if result is None:

24
discord/guild.py

@ -1298,26 +1298,20 @@ class Guild(Hashable):
def get_member_named(self, name: str, /) -> Optional[Member]:
"""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.
.. versionchanged:: 2.0
``name`` parameter is now positional-only.
.. versionchanged:: 2.1
``discriminator`` is no longer used in lookup, due to being removed on Discord.
Parameters
-----------
name: :class:`str`
The name of the member to lookup with an optional discriminator.
The name of the member to lookup.
Returns
--------
@ -1328,14 +1322,8 @@ class Guild(Hashable):
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:
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)

8
discord/http.py

@ -2894,7 +2894,7 @@ class HTTPClient:
def send_friend_request(self, username: str, discriminator: Snowflake) -> Response[None]:
r = Route('POST', '/users/@me/relationships')
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)
@ -3180,9 +3180,9 @@ class HTTPClient:
)
def add_app_whitelist(
self, app_id: Snowflake, username: str, discriminator: str
self, app_id: Snowflake, username: str, discriminator: Snowflake
) -> Response[application.WhitelistedUser]:
payload = {'username': username, 'discriminator': discriminator}
payload = {'username': username, 'discriminator': str(discriminator) or None}
return self.request(
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)
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(
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)
Returns the member's name with the discriminator.
Returns the member's name with a ``@``.
Attributes
----------
@ -253,7 +253,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
guild: :class:`Guild`
The guild that the member belongs to.
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`
Whether the member is pending member verification.
@ -287,6 +287,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
name: str
id: int
discriminator: str
global_name: Optional[str]
bot: bool
system: bool
created_at: datetime.datetime
@ -328,7 +329,7 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
def __repr__(self) -> str:
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}>'
)
@ -537,11 +538,11 @@ class Member(discord.abc.Messageable, discord.abc.Connectable, _UserTag):
def display_name(self) -> str:
""":class:`str`: Returns the user's display name.
For regular users this is just their username, but
if they have a guild specific nickname then that
For regular users this is just their global name or their username,
but if they have a guild specific nickname then that
is returned instead.
"""
return self.nick or self.name
return self.nick or self.global_name or self.name
@property
def display_avatar(self) -> Asset:

1
discord/state.py

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

15
discord/team.py

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

1
discord/types/user.py

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

56
discord/user.py

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

16
discord/widget.py

@ -121,7 +121,7 @@ class WidgetMember(BaseUser):
.. describe:: str(x)
Returns the widget member's ``name#discriminator``.
Returns the widget member's name with a ``@``.
Attributes
-----------
@ -130,13 +130,19 @@ class WidgetMember(BaseUser):
name: :class:`str`
The member's username.
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`
Whether the member is a bot.
status: :class:`Status`
The member's status.
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`]]
The member's activity.
deafened: Optional[:class:`bool`]
@ -189,9 +195,7 @@ class WidgetMember(BaseUser):
self.connected_channel: Optional[WidgetChannel] = connected_channel
def __repr__(self) -> str:
return (
f"<WidgetMember name={self.name!r} discriminator={self.discriminator!r}" f" bot={self.bot} nick={self.nick!r}>"
)
return f"<WidgetMember name={self.name!r} global_name={self.global_name!r} bot={self.bot} nick={self.nick!r}>"
@property
def display_name(self) -> str:

Loading…
Cancel
Save