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
Invite creation failed.
~discord.NotFound
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.
"""
channel = await self._get_channel()
await self._state.http.send_typing(channel.id)
@ -1508,7 +1506,6 @@ class Messageable:
:class:`~discord.Message`
The message asked for.
"""
channel = await self._get_channel()
data = await self._state.http.get_message(channel.id, id)
return self._state.create_message(channel=channel, data=data)
@ -1520,8 +1517,8 @@ class Messageable:
Raises
-------
HTTPException
Acking failed.
~discord.HTTPException
Acking the channel failed.
"""
channel = await self._get_channel()
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`]
The messages that are currently pinned.
"""
channel = await self._get_channel()
state = self._state
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",
and the state parameter has 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
-----------

42
discord/appinfo.py

@ -135,6 +135,24 @@ class PartialApplication(Hashable):
.. 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
-------------
id: :class:`int`
@ -196,6 +214,9 @@ class PartialApplication(Hashable):
self._state: ConnectionState = state
self._update(data)
def __str__(self) -> str:
return self.name
def _update(self, data: PartialAppInfoPayload) -> None:
self.id: int = int(data['id'])
self.name: str = data['name']
@ -504,6 +525,24 @@ class InteractionApplication(Hashable):
.. 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
-------------
id: :class:`int`
@ -537,6 +576,9 @@ class InteractionApplication(Hashable):
self._state: ConnectionState = state
self._update(data)
def __str__(self) -> str:
return self.name
def _update(self, data: dict) -> None:
self.id: int = int(data['id'])
self.name: str = data['name']

58
discord/commands.py

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

9
discord/components.py

@ -66,8 +66,7 @@ class Component:
- :class:`ActionRow`
- :class:`Button`
- :class:`SelectMenu`
This class is abstract and cannot be instantiated.
- :class:`TextInput`
.. versionadded:: 2.0
@ -161,7 +160,7 @@ class Button(Component):
emoji: Optional[:class:`PartialEmoji`]
The emoji of the button, if available.
message: :class:`Message`
The originating message, if any.
The originating message.
"""
__slots__: Tuple[str, ...] = (
@ -260,8 +259,6 @@ class SelectMenu(Component):
A list of options that can be selected in this menu.
disabled: :class:`bool`
Whether the select is disabled or not.
hash: :class:`str`
Unknown.
message: :class:`Message`
The originating message, if any.
"""
@ -291,7 +288,7 @@ class SelectMenu(Component):
def to_dict(self, options: Tuple[SelectOption]) -> dict:
return {
'compontent_type': self.type.value,
'component_type': self.type.value,
'custom_id': self.custom_id,
'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.
.. 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
----------
id: :class:`str`
@ -62,6 +80,25 @@ class PartialConnection:
def __init__(self, data: dict):
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):
self.id: str = data['id']
self.name: str = data['name']
@ -115,6 +152,8 @@ class Connection(PartialConnection):
----------
visible: :class:`bool`
Whether the connection is visible on your profile.
show_activity: :class:`bool`
Whether activities from this connection will be shown in presences.
Raises
------

2
discord/errors.py

@ -171,7 +171,7 @@ class DiscordServerError(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`.

17
discord/flags.py

@ -479,23 +479,6 @@ class PrivateUserFlags(PublicUserFlags):
.. note::
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
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.
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
----------
id: Union[:class:`str`, :class:`int`]
@ -67,6 +89,26 @@ class GuildFolder:
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
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):
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`.
"""
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
.. 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
------------
id: :class:`int`

26
discord/modal.py

@ -29,6 +29,7 @@ from .appinfo import InteractionApplication
from .components import _component_factory
from .enums import InteractionType
from .errors import InvalidData
from .mixins import Hashable
from .utils import time_snowflake, utcnow
if TYPE_CHECKING:
@ -42,11 +43,29 @@ __all__ = (
# fmt: on
class Modal:
class Modal(Hashable):
"""Represents a modal from the Discord Bot UI Kit.
.. 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
-----------
id: :class:`int`
@ -75,6 +94,9 @@ class Modal:
self.components: List[Component] = [_component_factory(d) for d in data.get('components', [])]
self.application: InteractionApplication = InteractionApplication(state=interaction._state, data=data['application'])
def __str__(self) -> str:
return self.title
def to_dict(self) -> dict:
return {
'id': str(self.id),
@ -87,7 +109,7 @@ class Modal:
Submits the modal.
The individual components must be already answered (if applicable).
All required components must be already answered.
Raises
-------

31
discord/relationship.py

@ -44,9 +44,23 @@ class Relationship:
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
-----------
nickname: :class:`str`
nickname: Optional[:class:`str`]
The user's friend nickname (if applicable).
user: :class:`User`
The user you have the relationship with.
@ -65,6 +79,17 @@ class Relationship:
def __repr__(self) -> str:
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:
"""|coro|
@ -103,6 +128,8 @@ class Relationship:
Changes a relationship's nickname. Only applicable for
type :class:`RelationshipType.friend`.
.. versionadded:: 1.9
Parameters
----------
nick: Optional[:class:`str`]
@ -112,8 +139,6 @@ class Relationship:
-------
HTTPException
Changing the nickname failed.
.. versionadded:: 1.9
"""
await self._state.http.change_friend_nickname(self.user.id, nick)
self.nickname = nick

71
discord/settings.py

@ -58,6 +58,8 @@ __all__ = (
class UserSettings:
"""Represents the Discord client settings.
.. versionadded:: 1.9
Attributes
----------
afk_timeout: :class:`int`
@ -341,6 +343,36 @@ class UserSettings:
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:
until = parse_time(config.get('end_time'))
if until is not None:
@ -357,18 +389,24 @@ class MuteConfig:
def __repr__(self) -> str:
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:
return bool(self.muted)
return self.muted
def __eq__(self, other) -> bool:
return self.muted == other
def __eq__(self, other: object) -> bool:
return self.muted == bool(other)
def __ne__(self, other) -> bool:
return not self.muted == other
def __ne__(self, other: object) -> bool:
return not self.muted == bool(other)
class ChannelSettings:
"""Represents a channel's notification settings"""
"""Represents a channel's notification settings."""
if TYPE_CHECKING:
_channel_id: int
@ -431,7 +469,6 @@ class ChannelSettings:
The new notification settings.
"""
payload = {}
data = None
if muted is not MISSING:
payload['muted'] = muted
@ -453,14 +490,10 @@ class ChannelSettings:
if level is not MISSING:
payload['message_notifications'] = level.value
if payload:
fields = {'channel_overrides': {str(self._channel_id): payload}}
data = await self._state.http.edit_guild_settings(self._guild_id, fields)
fields = {'channel_overrides': {str(self._channel_id): payload}}
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)
else:
return self
return ChannelSettings(self._guild_id, data=data['channel_overrides'][str(self._channel_id)], state=self._state)
class GuildSettings:
@ -552,7 +585,6 @@ class GuildSettings:
The new notification settings.
"""
payload = {}
data = None
if muted is not MISSING:
payload['muted'] = muted
@ -583,10 +615,7 @@ class GuildSettings:
if hide_muted_channels is not MISSING:
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 . import utils
from .user import BaseUser
from .asset import Asset
from .enums import TeamMembershipState, try_enum
from .mixins import Hashable
from .user import BaseUser
from typing import TYPE_CHECKING, Optional, overload, List, Union
@ -49,15 +50,33 @@ __all__ = (
)
class Team:
class Team(Hashable):
"""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
-------------
id: :class:`int`
The team ID.
name: :class:`str`
The team name
The team name.
owner_id: :class:`int`
The team's owner ID.
members: List[:class:`TeamMember`]
@ -75,6 +94,12 @@ class Team:
self._state: ConnectionState = state
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):
self.id: int = int(data['id'])
self.name: str = data['name']
@ -91,9 +116,6 @@ class Team:
}
members.append(TeamMember(self, self._state, member))
def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name}>'
@property
def icon(self) -> Optional[Asset]:
"""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.
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')
@ -240,9 +265,6 @@ class ContextProperties: # Thank you Discord-S.C.U.M
if data is not None:
return int(data)
def __bool__(self) -> bool:
return self.value is not None
def __str__(self) -> str:
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
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:

73
discord/user.py

@ -76,7 +76,29 @@ __all__ = (
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')
@ -175,15 +197,6 @@ class Note:
"""
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:
base = f'<Note user={self.user!r}'
note = self._note
@ -192,19 +205,14 @@ class Note:
base += f' note={note!r}'
return base + '>'
def __len__(self) -> int:
if note := self._note:
return len(note)
return 0
def __eq__(self, other: Note) -> bool:
try:
return isinstance(other, Note) and self._note == other._note and self._user_id == other._user_id
except TypeError:
return False
def __ne__(self, other: Note) -> bool:
return not self.__eq__(other)
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 __bool__(self) -> bool:
try:
@ -212,6 +220,22 @@ class Note:
except TypeError:
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:
__slots__ = ()
@ -301,6 +325,7 @@ class BaseUser(_UserTag):
'discriminator': self.discriminator,
'bot': self.bot,
'system': self.system,
'public_flags': self._public_flags,
}
@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.
note: :class:`Note`
The user's note. Not pre-fetched.
.. versionadded:: 1.9
nsfw_allowed: :class:`bool`
Specifies if the user should be allowed to access NSFW content.

Loading…
Cancel
Save