Browse Source

Documentation and operations fixes

pull/10109/head
dolfies 3 years ago
parent
commit
e08cdd073a
  1. 8
      discord/abc.py
  2. 2
      discord/activity.py
  3. 42
      discord/appinfo.py
  4. 58
      discord/commands.py
  5. 9
      discord/components.py
  6. 39
      discord/connections.py
  7. 2
      discord/errors.py
  8. 17
      discord/flags.py
  9. 57
      discord/guild_folder.py
  10. 14
      discord/interactions.py
  11. 26
      discord/modal.py
  12. 31
      discord/relationship.py
  13. 71
      discord/settings.py
  14. 34
      discord/team.py
  15. 35
      discord/tracking.py
  16. 73
      discord/user.py

8
discord/abc.py

@ -1170,7 +1170,6 @@ class GuildChannel:
------- -------
~discord.HTTPException ~discord.HTTPException
Invite creation failed. Invite creation failed.
~discord.NotFound ~discord.NotFound
The channel that was passed is a category or an invalid channel. The channel that was passed is a category or an invalid channel.
@ -1462,7 +1461,6 @@ class Messageable:
*Typing* indicator will go away after 10 seconds, or after a message is sent. *Typing* indicator will go away after 10 seconds, or after a message is sent.
""" """
channel = await self._get_channel() channel = await self._get_channel()
await self._state.http.send_typing(channel.id) await self._state.http.send_typing(channel.id)
@ -1508,7 +1506,6 @@ class Messageable:
:class:`~discord.Message` :class:`~discord.Message`
The message asked for. The message asked for.
""" """
channel = await self._get_channel() channel = await self._get_channel()
data = await self._state.http.get_message(channel.id, id) data = await self._state.http.get_message(channel.id, id)
return self._state.create_message(channel=channel, data=data) return self._state.create_message(channel=channel, data=data)
@ -1520,8 +1517,8 @@ class Messageable:
Raises Raises
------- -------
HTTPException ~discord.HTTPException
Acking failed. Acking the channel failed.
""" """
channel = await self._get_channel() channel = await self._get_channel()
await self._state.http.ack_message(channel.id, channel.last_message_id or utils.time_snowflake(utils.utcnow())) await self._state.http.ack_message(channel.id, channel.last_message_id or utils.time_snowflake(utils.utcnow()))
@ -1560,7 +1557,6 @@ class Messageable:
List[:class:`~discord.Message`] List[:class:`~discord.Message`]
The messages that are currently pinned. The messages that are currently pinned.
""" """
channel = await self._get_channel() channel = await self._get_channel()
state = self._state state = self._state
data = await state.http.pins_from(channel.id) data = await state.http.pins_from(channel.id)

2
discord/activity.py

@ -754,7 +754,7 @@ class CustomActivity(BaseActivity):
Technically, the name of custom activities is hardcoded to "Custom Status", Technically, the name of custom activities is hardcoded to "Custom Status",
and the state parameter has the actual custom text. and the state parameter has the actual custom text.
This is confusing, so here, the name represents the actual custom text. This is confusing, so here, the name represents the actual custom text.
However, the "correct" way still works. However, the "correct" way of initialization still works.
Attributes Attributes
----------- -----------

42
discord/appinfo.py

@ -135,6 +135,24 @@ class PartialApplication(Hashable):
.. versionadded:: 2.0 .. versionadded:: 2.0
.. container:: operations
.. describe:: x == y
Checks if two applications are equal.
.. describe:: x != y
Checks if two applications are not equal.
.. describe:: hash(x)
Return the application's hash.
.. describe:: str(x)
Returns the application's name.
Attributes Attributes
------------- -------------
id: :class:`int` id: :class:`int`
@ -196,6 +214,9 @@ class PartialApplication(Hashable):
self._state: ConnectionState = state self._state: ConnectionState = state
self._update(data) self._update(data)
def __str__(self) -> str:
return self.name
def _update(self, data: PartialAppInfoPayload) -> None: def _update(self, data: PartialAppInfoPayload) -> None:
self.id: int = int(data['id']) self.id: int = int(data['id'])
self.name: str = data['name'] self.name: str = data['name']
@ -504,6 +525,24 @@ class InteractionApplication(Hashable):
.. versionadded:: 2.0 .. versionadded:: 2.0
.. container:: operations
.. describe:: x == y
Checks if two applications are equal.
.. describe:: x != y
Checks if two applications are not equal.
.. describe:: hash(x)
Return the application's hash.
.. describe:: str(x)
Returns the application's name.
Attributes Attributes
------------- -------------
id: :class:`int` id: :class:`int`
@ -537,6 +576,9 @@ class InteractionApplication(Hashable):
self._state: ConnectionState = state self._state: ConnectionState = state
self._update(data) self._update(data)
def __str__(self) -> str:
return self.name
def _update(self, data: dict) -> None: def _update(self, data: dict) -> None:
self.id: int = int(data['id']) self.id: int = int(data['id'])
self.name: str = data['name'] self.name: str = data['name']

58
discord/commands.py

@ -88,6 +88,9 @@ class ApplicationCommand(Protocol):
target_channel: Optional[Messageable] target_channel: Optional[Messageable]
default_permission: bool default_permission: bool
def __str__(self) -> str:
return self.name
async def __call__(self, data, channel: Optional[Messageable] = None) -> Interaction: async def __call__(self, data, channel: Optional[Messageable] = None) -> Interaction:
channel = channel or self.target_channel channel = channel or self.target_channel
if channel is None: if channel is None:
@ -117,6 +120,24 @@ class ApplicationCommand(Protocol):
class BaseCommand(ApplicationCommand, Hashable): class BaseCommand(ApplicationCommand, Hashable):
"""Represents a base command. """Represents a base command.
.. container:: operations
.. describe:: x == y
Checks if two commands are equal.
.. describe:: x != y
Checks if two commands are not equal.
.. describe:: hash(x)
Return the command's hash.
.. describe:: str(x)
Returns the command's name.
Attributes Attributes
---------- ----------
id: :class:`int` id: :class:`int`
@ -163,7 +184,7 @@ class BaseCommand(ApplicationCommand, Hashable):
self._default_member_permissions = data['default_member_permissions'] self._default_member_permissions = data['default_member_permissions']
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name}>' return f'<{self.__class__.__name__} id={self.id} name={self.name!r}>'
def is_group(self) -> bool: def is_group(self) -> bool:
"""Query whether this command is a group. """Query whether this command is a group.
@ -451,7 +472,7 @@ class SlashCommand(BaseCommand, SlashMixin):
return await super().__call__(self._parse_kwargs(kwargs), channel) return await super().__call__(self._parse_kwargs(kwargs), channel)
def __repr__(self) -> str: def __repr__(self) -> str:
BASE = f'<SlashCommand id={self.id} name={self.name}' BASE = f'<SlashCommand id={self.id} name={self.name!r}'
if self.options: if self.options:
BASE += f' options={len(self.options)}' BASE += f' options={len(self.options)}'
if self.children: if self.children:
@ -474,6 +495,12 @@ class SubCommand(SlashMixin):
This could be a subcommand, or a subgroup. This could be a subcommand, or a subgroup.
.. container:: operations
.. describe:: str(x)
Returns the command's name.
Attributes Attributes
---------- ----------
parent: :class:`SlashCommand` parent: :class:`SlashCommand`
@ -506,6 +533,9 @@ class SubCommand(SlashMixin):
self._type: AppCommandOptionType = try_enum(AppCommandOptionType, data['type']) self._type: AppCommandOptionType = try_enum(AppCommandOptionType, data['type'])
self._unwrap_options(data.get('options', [])) self._unwrap_options(data.get('options', []))
def __str__(self) -> str:
return self.name
def _walk_parents(self): def _walk_parents(self):
parent = self.parent parent = self.parent
while True: while True:
@ -554,7 +584,7 @@ class SubCommand(SlashMixin):
return await super().__call__(options, channel) return await super().__call__(options, channel)
def __repr__(self) -> str: def __repr__(self) -> str:
BASE = f'<SubCommand name={self.name}' BASE = f'<SubCommand name={self.name!r}'
if self.options: if self.options:
BASE += f' options={len(self.options)}' BASE += f' options={len(self.options)}'
if self.children: if self.children:
@ -606,6 +636,12 @@ class SubCommand(SlashMixin):
class Option: # TODO: Add validation class Option: # TODO: Add validation
"""Represents a command option. """Represents a command option.
.. container:: operations
.. describe:: str(x)
Returns the option's name.
Attributes Attributes
---------- ----------
name: :class:`str` name: :class:`str`
@ -653,8 +689,11 @@ class Option: # TODO: Add validation
self.channel_types: List[ChannelType] = [try_enum(ChannelType, c) for c in data.get('channel_types', [])] self.channel_types: List[ChannelType] = [try_enum(ChannelType, c) for c in data.get('channel_types', [])]
self.autocomplete: bool = data.get('autocomplete', False) self.autocomplete: bool = data.get('autocomplete', False)
def __str__(self) -> str:
return self.name
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<Option name={self.name} type={self.type} required={self.required}>' return f'<Option name={self.name!r} type={self.type!r} required={self.required}>'
def _convert(self, value): def _convert(self, value):
for choice in self.choices: for choice in self.choices:
@ -666,6 +705,12 @@ class Option: # TODO: Add validation
class OptionChoice: class OptionChoice:
"""Represents a choice for an option. """Represents a choice for an option.
.. container:: operations
.. describe:: str(x)
Returns the choice's name.
Attributes Attributes
---------- ----------
name: :class:`str` name: :class:`str`
@ -686,8 +731,11 @@ class OptionChoice:
elif type is AppCommandOptionType.number: elif type is AppCommandOptionType.number:
self.value = float(data['value']) self.value = float(data['value'])
def __str__(self) -> str:
return self.name
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<OptionChoice name={self.name} value={self.value}>' return f'<OptionChoice name={self.name!r} value={self.value!r}>'
def _convert(self, value): def _convert(self, value):
if value == self.name: if value == self.name:

9
discord/components.py

@ -66,8 +66,7 @@ class Component:
- :class:`ActionRow` - :class:`ActionRow`
- :class:`Button` - :class:`Button`
- :class:`SelectMenu` - :class:`SelectMenu`
- :class:`TextInput`
This class is abstract and cannot be instantiated.
.. versionadded:: 2.0 .. versionadded:: 2.0
@ -161,7 +160,7 @@ class Button(Component):
emoji: Optional[:class:`PartialEmoji`] emoji: Optional[:class:`PartialEmoji`]
The emoji of the button, if available. The emoji of the button, if available.
message: :class:`Message` message: :class:`Message`
The originating message, if any. The originating message.
""" """
__slots__: Tuple[str, ...] = ( __slots__: Tuple[str, ...] = (
@ -260,8 +259,6 @@ class SelectMenu(Component):
A list of options that can be selected in this menu. A list of options that can be selected in this menu.
disabled: :class:`bool` disabled: :class:`bool`
Whether the select is disabled or not. Whether the select is disabled or not.
hash: :class:`str`
Unknown.
message: :class:`Message` message: :class:`Message`
The originating message, if any. The originating message, if any.
""" """
@ -291,7 +288,7 @@ class SelectMenu(Component):
def to_dict(self, options: Tuple[SelectOption]) -> dict: def to_dict(self, options: Tuple[SelectOption]) -> dict:
return { return {
'compontent_type': self.type.value, 'component_type': self.type.value,
'custom_id': self.custom_id, 'custom_id': self.custom_id,
'values': [option.value for option in options], 'values': [option.value for option in options],
} }

39
discord/connections.py

@ -41,6 +41,24 @@ class PartialConnection:
This is the info you get for other people's connections. This is the info you get for other people's connections.
.. container:: operations
.. describe:: x == y
Checks if two connections are equal.
.. describe:: x != y
Checks if two connections are not equal.
.. describe:: hash(x)
Return the connection's hash.
.. describe:: str(x)
Returns the connection's name.
Attributes Attributes
---------- ----------
id: :class:`str` id: :class:`str`
@ -62,6 +80,25 @@ class PartialConnection:
def __init__(self, data: dict): def __init__(self, data: dict):
self._update(data) self._update(data)
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id!r} name={self.name!r} type={self.type!r} visible={self.visible}>'
def __hash__(self) -> int:
return hash((self.name, self.id))
def __eq__(self, other: object) -> bool:
if isinstance(other, PartialConnection):
return self.id == other.id and self.name == other.name
return False
def __ne__(self, other: object) -> bool:
if isinstance(other, PartialConnection):
return self.id != other.id or self.name != other.name
return True
def _update(self, data: dict): def _update(self, data: dict):
self.id: str = data['id'] self.id: str = data['id']
self.name: str = data['name'] self.name: str = data['name']
@ -115,6 +152,8 @@ class Connection(PartialConnection):
---------- ----------
visible: :class:`bool` visible: :class:`bool`
Whether the connection is visible on your profile. Whether the connection is visible on your profile.
show_activity: :class:`bool`
Whether activities from this connection will be shown in presences.
Raises Raises
------ ------

2
discord/errors.py

@ -171,7 +171,7 @@ class DiscordServerError(HTTPException):
class CaptchaRequired(HTTPException): class CaptchaRequired(HTTPException):
"""Exception that's raised when a captcha is required and no handler exists. """Exception that's raised when a captcha is required and isn't handled.
Subclass of :exc:`HTTPException`. Subclass of :exc:`HTTPException`.

17
discord/flags.py

@ -479,23 +479,6 @@ class PrivateUserFlags(PublicUserFlags):
.. note:: .. note::
These are only available on your own user flags. These are only available on your own user flags.
.. container:: operations
.. describe:: x == y
Checks if two UserFlags are equal.
.. describe:: x != y
Checks if two UserFlags are not equal.
.. describe:: hash(x)
Return the flag's hash.
.. describe:: iter(x)
Returns an iterator of ``(name, value)`` pairs. This allows it
to be, for example, constructed as a dict or a list of pairs.
Note that aliases are not shown.
.. versionadded:: 2.0 .. versionadded:: 2.0
Attributes Attributes

57
discord/guild_folder.py

@ -48,6 +48,28 @@ class GuildFolder:
Guilds not in folders *are* actually in folders API wise, with them being the only member. Guilds not in folders *are* actually in folders API wise, with them being the only member.
Because Discord. Because Discord.
.. container:: operations
.. describe:: x == y
Checks if two guild folders are equal.
.. describe:: x != y
Checks if two guild folders are not equal.
.. describe:: hash(x)
Return the folder's hash.
.. describe:: str(x)
Returns the folder's name.
.. describe:: len(x)
Returns the number of guilds in the folder.
Attributes Attributes
---------- ----------
id: Union[:class:`str`, :class:`int`] id: Union[:class:`str`, :class:`int`]
@ -67,6 +89,26 @@ class GuildFolder:
self._colour: int = data['color'] self._colour: int = data['color']
self.guilds: List[Guild] = list(filter(None, map(self._get_guild, data['guild_ids']))) # type: ignore # Lying for better developer UX self.guilds: List[Guild] = list(filter(None, map(self._get_guild, data['guild_ids']))) # type: ignore # Lying for better developer UX
def __str__(self) -> str:
return self.name or 'None'
def __repr__(self) -> str:
return f'<GuildFolder id={self.id} name={self.name} guilds={self.guilds!r}>'
def __eq__(self, other) -> bool:
return isinstance(other, GuildFolder) and self.id == other.id
def __ne__(self, other) -> bool:
if isinstance(other, GuildFolder):
return self.id != other.id
return True
def __hash__(self) -> int:
return hash(self.id)
def __len__(self) -> int:
return len(self.guilds)
def _get_guild(self, id): def _get_guild(self, id):
return self._state._get_guild(int(id)) or Object(id=int(id)) return self._state._get_guild(int(id)) or Object(id=int(id))
@ -86,18 +128,3 @@ class GuildFolder:
This is an alias for :attr:`colour`. This is an alias for :attr:`colour`.
""" """
return self.colour return self.colour
def __str__(self) -> str:
return self.name or 'None'
def __repr__(self) -> str:
return f'<GuildFolder id={self.id} name={self.name} guilds={self.guilds!r}>'
def __len__(self) -> int:
return len(self.name)
def __eq__(self, other) -> bool:
return isinstance(other, GuildFolder) and self.id == other.id
def __ne__(self, other) -> bool:
return not self.__eq__(other)

14
discord/interactions.py

@ -55,6 +55,20 @@ class Interaction(Hashable):
.. versionadded:: 2.0 .. versionadded:: 2.0
.. container:: operations
.. describe:: x == y
Checks if two interactions are equal.
.. describe:: x != y
Checks if two interactions are not equal.
.. describe:: hash(x)
Return the interaction's hash.
Attributes Attributes
------------ ------------
id: :class:`int` id: :class:`int`

26
discord/modal.py

@ -29,6 +29,7 @@ from .appinfo import InteractionApplication
from .components import _component_factory from .components import _component_factory
from .enums import InteractionType from .enums import InteractionType
from .errors import InvalidData from .errors import InvalidData
from .mixins import Hashable
from .utils import time_snowflake, utcnow from .utils import time_snowflake, utcnow
if TYPE_CHECKING: if TYPE_CHECKING:
@ -42,11 +43,29 @@ __all__ = (
# fmt: on # fmt: on
class Modal: class Modal(Hashable):
"""Represents a modal from the Discord Bot UI Kit. """Represents a modal from the Discord Bot UI Kit.
.. versionadded:: 2.0 .. versionadded:: 2.0
.. container:: operations
.. describe:: x == y
Checks if two modals are equal.
.. describe:: x != y
Checks if two modals are not equal.
.. describe:: hash(x)
Return the modal's hash.
.. describe:: str(x)
Returns the modal's title.
Attributes Attributes
----------- -----------
id: :class:`int` id: :class:`int`
@ -75,6 +94,9 @@ class Modal:
self.components: List[Component] = [_component_factory(d) for d in data.get('components', [])] self.components: List[Component] = [_component_factory(d) for d in data.get('components', [])]
self.application: InteractionApplication = InteractionApplication(state=interaction._state, data=data['application']) self.application: InteractionApplication = InteractionApplication(state=interaction._state, data=data['application'])
def __str__(self) -> str:
return self.title
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {
'id': str(self.id), 'id': str(self.id),
@ -87,7 +109,7 @@ class Modal:
Submits the modal. Submits the modal.
The individual components must be already answered (if applicable). All required components must be already answered.
Raises Raises
------- -------

31
discord/relationship.py

@ -44,9 +44,23 @@ class Relationship:
A relationship is like a friendship, a person who is blocked, etc. A relationship is like a friendship, a person who is blocked, etc.
.. container:: operations
.. describe:: x == y
Checks if two relationships are equal.
.. describe:: x != y
Checks if two relationships are not equal.
.. describe:: hash(x)
Return the relationship's hash.
Attributes Attributes
----------- -----------
nickname: :class:`str` nickname: Optional[:class:`str`]
The user's friend nickname (if applicable). The user's friend nickname (if applicable).
user: :class:`User` user: :class:`User`
The user you have the relationship with. The user you have the relationship with.
@ -65,6 +79,17 @@ class Relationship:
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<Relationship user={self.user!r} type={self.type!r}>' return f'<Relationship user={self.user!r} type={self.type!r}>'
def __eq__(self, other: object) -> bool:
return isinstance(other, Relationship) and other.user.id == self.user.id
def __ne__(self, other: object) -> bool:
if isinstance(other, Relationship):
return other.user.id != self.user.id
return True
def __hash__(self) -> int:
return self.user.__hash__()
async def delete(self) -> None: async def delete(self) -> None:
"""|coro| """|coro|
@ -103,6 +128,8 @@ class Relationship:
Changes a relationship's nickname. Only applicable for Changes a relationship's nickname. Only applicable for
type :class:`RelationshipType.friend`. type :class:`RelationshipType.friend`.
.. versionadded:: 1.9
Parameters Parameters
---------- ----------
nick: Optional[:class:`str`] nick: Optional[:class:`str`]
@ -112,8 +139,6 @@ class Relationship:
------- -------
HTTPException HTTPException
Changing the nickname failed. Changing the nickname failed.
.. versionadded:: 1.9
""" """
await self._state.http.change_friend_nickname(self.user.id, nick) await self._state.http.change_friend_nickname(self.user.id, nick)
self.nickname = nick self.nickname = nick

71
discord/settings.py

@ -58,6 +58,8 @@ __all__ = (
class UserSettings: class UserSettings:
"""Represents the Discord client settings. """Represents the Discord client settings.
.. versionadded:: 1.9
Attributes Attributes
---------- ----------
afk_timeout: :class:`int` afk_timeout: :class:`int`
@ -341,6 +343,36 @@ class UserSettings:
class MuteConfig: class MuteConfig:
"""An object representing an object's mute status.
.. versionadded:: 2.0
.. container:: operations
.. describe:: x == y
Checks if two items are muted.
.. describe:: x != y
Checks if two items are not muted.
.. describe:: str(x)
Returns the mute status as a string.
.. describe:: int(x)
Returns the mute status as an int.
Attributes
----------
muted: :class:`bool`
Indicates if the object is muted.
until: Optional[:class:`datetime.datetime`]
When the mute will expire.
"""
def __init__(self, muted: bool, config: Dict[str, str]) -> None: def __init__(self, muted: bool, config: Dict[str, str]) -> None:
until = parse_time(config.get('end_time')) until = parse_time(config.get('end_time'))
if until is not None: if until is not None:
@ -357,18 +389,24 @@ class MuteConfig:
def __repr__(self) -> str: def __repr__(self) -> str:
return f'<MuteConfig muted={self.muted} until={self.until}>' return f'<MuteConfig muted={self.muted} until={self.until}>'
def __str__(self) -> str:
return str(self.muted)
def __int__(self) -> int:
return int(self.muted)
def __bool__(self) -> bool: def __bool__(self) -> bool:
return bool(self.muted) return self.muted
def __eq__(self, other) -> bool: def __eq__(self, other: object) -> bool:
return self.muted == other return self.muted == bool(other)
def __ne__(self, other) -> bool: def __ne__(self, other: object) -> bool:
return not self.muted == other return not self.muted == bool(other)
class ChannelSettings: class ChannelSettings:
"""Represents a channel's notification settings""" """Represents a channel's notification settings."""
if TYPE_CHECKING: if TYPE_CHECKING:
_channel_id: int _channel_id: int
@ -431,7 +469,6 @@ class ChannelSettings:
The new notification settings. The new notification settings.
""" """
payload = {} payload = {}
data = None
if muted is not MISSING: if muted is not MISSING:
payload['muted'] = muted payload['muted'] = muted
@ -453,14 +490,10 @@ class ChannelSettings:
if level is not MISSING: if level is not MISSING:
payload['message_notifications'] = level.value payload['message_notifications'] = level.value
if payload: fields = {'channel_overrides': {str(self._channel_id): payload}}
fields = {'channel_overrides': {str(self._channel_id): payload}} data = await self._state.http.edit_guild_settings(self._guild_id, fields)
data = await self._state.http.edit_guild_settings(self._guild_id, fields)
if data: return ChannelSettings(self._guild_id, data=data['channel_overrides'][str(self._channel_id)], state=self._state)
return ChannelSettings(self._guild_id, data=data['channel_overrides'][str(self._channel_id)], state=self._state)
else:
return self
class GuildSettings: class GuildSettings:
@ -552,7 +585,6 @@ class GuildSettings:
The new notification settings. The new notification settings.
""" """
payload = {} payload = {}
data = None
if muted is not MISSING: if muted is not MISSING:
payload['muted'] = muted payload['muted'] = muted
@ -583,10 +615,7 @@ class GuildSettings:
if hide_muted_channels is not MISSING: if hide_muted_channels is not MISSING:
payload['hide_muted_channels'] = hide_muted_channels payload['hide_muted_channels'] = hide_muted_channels
if payload: data = await self._state.http.edit_guild_settings(self._guild_id, payload)
data = await self._state.http.edit_guild_settings(self._guild_id, payload)
return GuildSettings(data=data, state=self._state)
if data:
return GuildSettings(data=data, state=self._state)
else:
return self

34
discord/team.py

@ -25,9 +25,10 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations from __future__ import annotations
from . import utils from . import utils
from .user import BaseUser
from .asset import Asset from .asset import Asset
from .enums import TeamMembershipState, try_enum from .enums import TeamMembershipState, try_enum
from .mixins import Hashable
from .user import BaseUser
from typing import TYPE_CHECKING, Optional, overload, List, Union from typing import TYPE_CHECKING, Optional, overload, List, Union
@ -49,15 +50,33 @@ __all__ = (
) )
class Team: class Team(Hashable):
"""Represents an application team. """Represents an application team.
.. container:: operations
.. describe:: x == y
Checks if two teams are equal.
.. describe:: x != y
Checks if two teams are not equal.
.. describe:: hash(x)
Return the team's hash.
.. describe:: str(x)
Returns the team's name.
Attributes Attributes
------------- -------------
id: :class:`int` id: :class:`int`
The team ID. The team ID.
name: :class:`str` name: :class:`str`
The team name The team name.
owner_id: :class:`int` owner_id: :class:`int`
The team's owner ID. The team's owner ID.
members: List[:class:`TeamMember`] members: List[:class:`TeamMember`]
@ -75,6 +94,12 @@ class Team:
self._state: ConnectionState = state self._state: ConnectionState = state
self._update(data) self._update(data)
def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name}>'
def __str__(self) -> str:
return self.name
def _update(self, data: TeamPayload): def _update(self, data: TeamPayload):
self.id: int = int(data['id']) self.id: int = int(data['id'])
self.name: str = data['name'] self.name: str = data['name']
@ -91,9 +116,6 @@ class Team:
} }
members.append(TeamMember(self, self._state, member)) members.append(TeamMember(self, self._state, member))
def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name}>'
@property @property
def icon(self) -> Optional[Asset]: def icon(self) -> Optional[Asset]:
"""Optional[:class:`.Asset`]: Retrieves the team's icon asset, if any.""" """Optional[:class:`.Asset`]: Retrieves the team's icon asset, if any."""

35
discord/tracking.py

@ -49,6 +49,31 @@ class ContextProperties: # Thank you Discord-S.C.U.M
"""Represents the Discord X-Context-Properties header. """Represents the Discord X-Context-Properties header.
This header is essential for certain actions (e.g. joining guilds, friend requesting). This header is essential for certain actions (e.g. joining guilds, friend requesting).
.. versionadded:: 1.9
.. container:: operations
.. describe:: x == y
Checks if two context properties are equal.
.. describe:: x != y
Checks if two context properties are not equal.
.. describe:: hash(x)
Return the context property's hash.
.. describe:: str(x)
Returns the context property's name.
Attributes
----------
value: :class:`str`
The encoded header value.
""" """
__slots__ = ('_data', 'value') __slots__ = ('_data', 'value')
@ -240,9 +265,6 @@ class ContextProperties: # Thank you Discord-S.C.U.M
if data is not None: if data is not None:
return int(data) return int(data)
def __bool__(self) -> bool:
return self.value is not None
def __str__(self) -> str: def __str__(self) -> str:
return self.target or 'None' return self.target or 'None'
@ -253,7 +275,12 @@ class ContextProperties: # Thank you Discord-S.C.U.M
return isinstance(other, ContextProperties) and self.value == other.value return isinstance(other, ContextProperties) and self.value == other.value
def __ne__(self, other) -> bool: def __ne__(self, other) -> bool:
return not self.__eq__(other) if isinstance(other, ContextProperties):
return self.value != other.value
return True
def __hash__(self) -> int:
return hash(self.value)
class Tracking: class Tracking:

73
discord/user.py

@ -76,7 +76,29 @@ __all__ = (
class Note: class Note:
"""Represents a Discord note.""" """Represents a Discord note.
.. container:: operations
.. describe:: x == y
Checks if two notes are equal.
.. describe:: x != y
Checks if two notes are not equal.
.. describe:: hash(x)
Returns the note's hash.
.. describe:: str(x)
Returns the note's content.
Raises :exc:`ClientException` if the note is not fetched.
.. describe:: bool(x)
Returns the note's content as a boolean.
.. describe:: len(x)
Returns the note's length.
"""
__slots__ = ('_state', '_note', '_user_id', '_user') __slots__ = ('_state', '_note', '_user_id', '_user')
@ -175,15 +197,6 @@ class Note:
""" """
await self.edit(None) await self.edit(None)
def __str__(self) -> str:
note = self._note
if note is MISSING:
raise ClientException('Note is not fetched')
elif note is None:
return ''
else:
return note
def __repr__(self) -> str: def __repr__(self) -> str:
base = f'<Note user={self.user!r}' base = f'<Note user={self.user!r}'
note = self._note note = self._note
@ -192,19 +205,14 @@ class Note:
base += f' note={note!r}' base += f' note={note!r}'
return base + '>' return base + '>'
def __len__(self) -> int: def __str__(self) -> str:
if note := self._note: note = self._note
return len(note) if note is MISSING:
return 0 raise ClientException('Note is not fetched')
elif note is None:
def __eq__(self, other: Note) -> bool: return ''
try: else:
return isinstance(other, Note) and self._note == other._note and self._user_id == other._user_id return note
except TypeError:
return False
def __ne__(self, other: Note) -> bool:
return not self.__eq__(other)
def __bool__(self) -> bool: def __bool__(self) -> bool:
try: try:
@ -212,6 +220,22 @@ class Note:
except TypeError: except TypeError:
return False return False
def __eq__(self, other: object) -> bool:
return isinstance(other, Note) and self._note == other._note and self._user_id == other._user_id
def __ne__(self, other: object) -> bool:
if isinstance(other, Note):
return self._note != other._note or self._user_id != other._user_id
return True
def __hash__(self) -> int:
return hash((self._note, self._user_id))
def __len__(self) -> int:
if note := self._note:
return len(note)
return 0
class _UserTag: class _UserTag:
__slots__ = () __slots__ = ()
@ -301,6 +325,7 @@ class BaseUser(_UserTag):
'discriminator': self.discriminator, 'discriminator': self.discriminator,
'bot': self.bot, 'bot': self.bot,
'system': self.system, 'system': self.system,
'public_flags': self._public_flags,
} }
@property @property
@ -501,6 +526,8 @@ class ClientUser(BaseUser):
Specifies the type of premium a user has (i.e. Nitro or Nitro Classic). Could be None if the user is not premium. Specifies the type of premium a user has (i.e. Nitro or Nitro Classic). Could be None if the user is not premium.
note: :class:`Note` note: :class:`Note`
The user's note. Not pre-fetched. The user's note. Not pre-fetched.
.. versionadded:: 1.9
nsfw_allowed: :class:`bool` nsfw_allowed: :class:`bool`
Specifies if the user should be allowed to access NSFW content. Specifies if the user should be allowed to access NSFW content.

Loading…
Cancel
Save