Browse Source

Run black

pull/10109/head
dolfies 3 years ago
parent
commit
957a484306
  1. 1
      discord/__init__.py
  2. 2
      discord/abc.py
  3. 25
      discord/activity.py
  4. 23
      discord/appinfo.py
  5. 17
      discord/calls.py
  6. 6
      discord/channel.py
  7. 33
      discord/client.py
  8. 55
      discord/commands.py
  9. 13
      discord/components.py
  10. 54
      discord/enums.py
  11. 10
      discord/errors.py
  12. 4
      discord/ext/commands/context.py
  13. 42
      discord/flags.py
  14. 55
      discord/gateway.py
  15. 8
      discord/guild.py
  16. 1
      discord/guild_folder.py
  17. 307
      discord/http.py
  18. 7
      discord/interactions.py
  19. 6
      discord/invite.py
  20. 9
      discord/iterators.py
  21. 2
      discord/message.py
  22. 5
      discord/modal.py
  23. 6
      discord/profile.py
  24. 24
      discord/settings.py
  25. 66
      discord/state.py
  26. 54
      discord/tracking.py
  27. 2
      discord/types/appinfo.py
  28. 2
      discord/types/guild.py
  29. 22
      discord/user.py
  30. 39
      discord/utils.py
  31. 22
      discord/voice_client.py
  32. 4
      discord/welcome_screen.py

1
discord/__init__.py

@ -73,6 +73,7 @@ class _VersionInfo(NamedTuple):
releaselevel: Literal['alpha', 'beta', 'candidate', 'final']
serial: int
version_info: _VersionInfo = _VersionInfo(major=2, minor=0, micro=0, releaselevel='alpha', serial=2)
logging.getLogger(__name__).addHandler(logging.NullHandler())

2
discord/abc.py

@ -1778,7 +1778,7 @@ class Connectable(Protocol):
timeout: float = 60.0,
reconnect: bool = True,
cls: Callable[[Client, Connectable], T] = MISSING,
_channel: Optional[Connectable] = None
_channel: Optional[Connectable] = None,
) -> T:
"""|coro|

25
discord/activity.py

@ -254,15 +254,15 @@ class Activity(BaseActivity):
def __eq__(self, other):
return (
isinstance(other, Activity) and
other.type == self.type and
other.name == self.name and
other.url == self.url and
other.emoji == self.emoji and
other.state == self.state and
other.session_id == self.session_id and
other.sync_id == self.sync_id and
other.start == self.start
isinstance(other, Activity)
and other.type == self.type
and other.name == self.name
and other.url == self.url
and other.emoji == self.emoji
and other.state == self.state
and other.session_id == self.session_id
and other.sync_id == self.sync_id
and other.start == self.start
)
def __ne__(self, other):
@ -810,9 +810,9 @@ class CustomActivity(BaseActivity):
def to_settings_dict(self) -> Dict[str, Any]:
o: Dict[str, Optional[Union[str, int]]] = {}
if (text := self.name):
if text := self.name:
o['text'] = text
if (emoji := self.emoji):
if emoji := self.emoji:
o['emoji_name'] = emoji.name
if emoji.id:
o['emoji_id'] = emoji.id
@ -880,6 +880,7 @@ def create_activity(data: Optional[ActivityPayload]) -> Optional[ActivityTypes]:
return Spotify(**data)
return Activity(**data)
def create_settings_activity(*, data, state):
if not data:
return
@ -891,4 +892,4 @@ def create_settings_activity(*, data, state):
elif (emoji_name := data.get('emoji_name')) is not None:
emoji = PartialEmoji(name=emoji_name)
return CustomActivity(name=data.get('text'), emoji=emoji, expires_at=data.get('expires_at'))
return CustomActivity(name=data.get('text'), emoji=emoji, expires_at=data.get('expires_at'))

23
discord/appinfo.py

@ -67,6 +67,7 @@ class ApplicationBot(User):
Whether the bot requires the completion of the full OAuth2 code
grant flow to join.
"""
__slots__ = ('public', 'require_code_grant')
def __init__(self, *, data, state: ConnectionState, application: Application):
@ -179,7 +180,7 @@ class PartialApplication(Hashable):
'terms_of_service_url',
'privacy_policy_url',
'_icon',
'_flags'
'_flags',
'_cover_image',
'public',
'require_code_grant',
@ -213,10 +214,22 @@ class PartialApplication(Hashable):
self.tags: List[str] = data.get('tags', [])
install_params = data.get('install_params', {})
self.install_url = data.get('custom_install_url') if not install_params else utils.oauth_url(self.id, permissions=Permissions(int(install_params.get('permissions', 0))), scopes=install_params.get('scopes', utils.MISSING))
self.install_url = (
data.get('custom_install_url')
if not install_params
else utils.oauth_url(
self.id,
permissions=Permissions(int(install_params.get('permissions', 0))),
scopes=install_params.get('scopes', utils.MISSING),
)
)
self.public: bool = data.get('integration_public', data.get('bot_public', True)) # The two seem to be used interchangeably?
self.require_code_grant: bool = data.get('integration_require_code_grant', data.get('bot_require_code_grant', False)) # Same here
self.public: bool = data.get(
'integration_public', data.get('bot_public', True)
) # The two seem to be used interchangeably?
self.require_code_grant: bool = data.get(
'integration_require_code_grant', data.get('bot_require_code_grant', False)
) # Same here
def __repr__(self) -> str:
return f'<{self.__class__.__name__} id={self.id} name={self.name!r} description={self.description!r}>'
@ -311,7 +324,7 @@ class Application(PartialApplication):
team: Optional[TeamPayload] = data.get('team')
self.team: Optional[Team] = Team(state, team) if team else None
if (bot := data.get('bot')):
if bot := data.get('bot'):
bot['public'] = data.get('bot_public', self.public)
bot['require_code_grant'] = data.get('bot_require_code_grant', self.require_code_grant)
self.bot: Optional[ApplicationBot] = ApplicationBot(data=bot, state=state, application=self) if bot else None

17
discord/calls.py

@ -56,6 +56,7 @@ def _running_only(func: Callable):
raise ClientException('Call is over')
else:
return func(self, *args, **kwargs)
return decorator
@ -75,9 +76,7 @@ class CallMessage:
The message associated with this call message.
"""
def __init__(
self, message: Message, *, participants: List[User], ended_timestamp: str
) -> None:
def __init__(self, message: Message, *, participants: List[User], ended_timestamp: str) -> None:
self.message = message
self.ended_timestamp = utils.parse_time(ended_timestamp)
self.participants = participants
@ -175,9 +174,7 @@ class PrivateCall:
state = self.voice_state_for(user)
return bool(state and state.channel and state.channel.id == self._channel_id)
def _update(
self, *, ringing: SnowflakeList = [], region: str = MISSING
) -> None:
def _update(self, *, ringing: SnowflakeList = [], region: str = MISSING) -> None:
if region is not MISSING:
self.region = region
channel = self.channel
@ -206,7 +203,9 @@ class PrivateCall:
@property
def voice_states(self) -> Dict[int, VoiceState]:
"""Mapping[:class:`int`, :class:`VoiceState`]: Returns a mapping of user IDs who have voice states in this call."""
return {k: v for k, v in self._state._voice_states.items() if bool(v and v.channel and v.channel.id == self._channel_id)}
return {
k: v for k, v in self._state._voice_states.items() if bool(v and v.channel and v.channel.id == self._channel_id)
}
async def fetch_message(self) -> Optional[Message]:
"""|coro|
@ -440,9 +439,7 @@ class GroupCall(PrivateCall):
if TYPE_CHECKING:
channel: GroupChannel
def _update(
self, *, ringing: List[int] = [], region: str = MISSING
) -> None:
def _update(self, *, ringing: List[int] = [], region: str = MISSING) -> None:
if region is not MISSING:
self.region = region

6
discord/channel.py

@ -2227,7 +2227,10 @@ class GroupChannel(discord.abc.Messageable, discord.abc.Connectable, Hashable):
@overload
async def edit(
self, *, name: Optional[str] = ..., icon: Optional[bytes] = ...,
self,
*,
name: Optional[str] = ...,
icon: Optional[bytes] = ...,
) -> Optional[GroupChannel]:
...
@ -2326,7 +2329,6 @@ class GroupChannel(discord.abc.Messageable, discord.abc.Connectable, Hashable):
return await super().connect(timeout=timeout, reconnect=reconnect, cls=cls)
class PartialMessageable(discord.abc.Messageable, Hashable):
"""Represents a partial messageable to aid with working messageable channels when
only a channel ID are present.

33
discord/client.py

@ -236,10 +236,7 @@ class Client:
connector, proxy=proxy, proxy_auth=proxy_auth, unsync_clock=unsync_clock, loop=self.loop
)
self._handlers: Dict[str, Callable] = {
'ready': self._handle_ready,
'connect': self._handle_connect
}
self._handlers: Dict[str, Callable] = {'ready': self._handle_ready, 'connect': self._handle_connect}
self._hooks: Dict[str, Callable] = {
'before_identify': self._call_before_identify_hook,
@ -265,9 +262,15 @@ class Client:
# Internals
def _get_state(self, **options: Any) -> ConnectionState:
return ConnectionState(dispatch=self.dispatch, handlers=self._handlers,
hooks=self._hooks, http=self.http, loop=self.loop,
client=self, **options)
return ConnectionState(
dispatch=self.dispatch,
handlers=self._handlers,
hooks=self._hooks,
http=self.http,
loop=self.loop,
client=self,
**options,
)
def _handle_ready(self) -> None:
self._ready.set()
@ -857,7 +860,7 @@ class Client:
The client may have multiple activities, these can be accessed under :attr:`activities`.
"""
if (activities := self.activities):
if activities := self.activities:
return activities[0]
@property
@ -1342,7 +1345,7 @@ class Client:
self_mute: bool = False,
self_deaf: bool = False,
self_video: bool = False,
preferred_region: Optional[str] = MISSING
preferred_region: Optional[str] = MISSING,
) -> None:
"""|coro|
@ -1380,11 +1383,7 @@ class Client:
# Guild stuff
async def fetch_guilds(
self,
*,
with_counts: bool = True
) -> List[Guild]:
async def fetch_guilds(self, *, with_counts: bool = True) -> List[Guild]:
"""Retrieves all your your guilds.
.. note::
@ -1700,7 +1699,7 @@ class Client:
state = self._connection
type = invite.type
if (message := invite._message):
if message := invite._message:
kwargs = {'message': message}
else:
kwargs = {
@ -1883,10 +1882,10 @@ class Client:
if ch_type in (ChannelType.group, ChannelType.private):
# The factory will be a DMChannel or GroupChannel here
channel = factory(me=self.user, data=data, state=self._connection) # type: ignore
channel = factory(me=self.user, data=data, state=self._connection) # type: ignore
else:
# The factory can't be a DMChannel or GroupChannel here
guild_id = int(data['guild_id']) # type: ignore
guild_id = int(data['guild_id']) # type: ignore
guild = self.get_guild(guild_id) or Object(id=guild_id)
# GuildChannels expect a Guild, we may be passing an Object
channel = factory(guild=guild, state=self._connection, data=data) # type: ignore

55
discord/commands.py

@ -98,7 +98,9 @@ class ApplicationCommand(Protocol):
state._interaction_cache[nonce] = (type.value, data['name'], acc_channel)
try:
await state.http.interact(type, data, acc_channel, form_data=True, nonce=nonce, application_id=self._application_id)
await state.http.interact(
type, data, acc_channel, form_data=True, nonce=nonce, application_id=self._application_id
)
i = await state.client.wait_for(
'interaction_finish',
check=lambda d: d.nonce == nonce,
@ -145,9 +147,7 @@ class BaseCommand(ApplicationCommand):
'_default_member_permissions',
)
def __init__(
self, *, state: ConnectionState, data: Dict[str, Any], channel: Optional[Messageable] = None
) -> None:
def __init__(self, *, state: ConnectionState, data: Dict[str, Any], channel: Optional[Messageable] = None) -> None:
self._state = state
self._data = data
self.name = data['name']
@ -180,12 +180,12 @@ class BaseCommand(ApplicationCommand):
def application(self):
"""The application this command belongs to."""
...
#return self._state.get_application(self._application_id)
# return self._state.get_application(self._application_id)
@property
def target_channel(self) -> Optional[Messageable]:
"""Optional[:class:`Messageable`]: The channel this application command will be used on.
You can set this in order to use this command in a different channel without re-fetching it.
"""
return self._channel
@ -193,6 +193,7 @@ class BaseCommand(ApplicationCommand):
@target_channel.setter
def target_channel(self, value: Optional[Messageable]) -> None:
from .abc import Messageable
if not isinstance(value, Messageable) and value is not None:
raise TypeError('channel must derive from Messageable')
self._channel = value
@ -280,9 +281,7 @@ class UserCommand(BaseCommand):
super().__init__(**kwargs)
self._user = user
async def __call__(
self, user: Optional[Snowflake] = None, *, channel: Optional[Messageable] = None
):
async def __call__(self, user: Optional[Snowflake] = None, *, channel: Optional[Messageable] = None):
"""Use the user command.
Parameters
@ -315,7 +314,7 @@ class UserCommand(BaseCommand):
@property
def target_user(self) -> Optional[Snowflake]:
"""Optional[:class:`Snowflake`]: The user this application command will be used on.
You can set this in order to use this command on a different user without re-fetching it.
"""
return self._user
@ -323,6 +322,7 @@ class UserCommand(BaseCommand):
@target_user.setter
def target_user(self, value: Optional[Snowflake]) -> None:
from .abc import Snowflake
if not isinstance(value, Snowflake) and value is not None:
raise TypeError('user must be Snowflake')
self._user = value
@ -351,9 +351,7 @@ class MessageCommand(BaseCommand):
super().__init__(**kwargs)
self._message = message
async def __call__(
self, message: Optional[Message] = None, *, channel: Optional[Messageable] = None
):
async def __call__(self, message: Optional[Message] = None, *, channel: Optional[Messageable] = None):
"""Use the message command.
Parameters
@ -386,7 +384,7 @@ class MessageCommand(BaseCommand):
@property
def target_message(self) -> Optional[Message]:
"""Optional[:class:`Message`]: The message this application command will be used on.
You can set this in order to use this command on a different message without re-fetching it.
"""
return self._message
@ -394,6 +392,7 @@ class MessageCommand(BaseCommand):
@target_message.setter
def target_message(self, value: Optional[Message]) -> None:
from .message import Message
if not isinstance(value, Message) and value is not None:
raise TypeError('message must be Message')
self._message = value
@ -423,9 +422,7 @@ class SlashCommand(BaseCommand, SlashMixin):
__slots__ = ('_parent', 'options', 'children')
def __init__(
self, *, data: Dict[str, Any], **kwargs
) -> None:
def __init__(self, *, data: Dict[str, Any], **kwargs) -> None:
super().__init__(data=data, **kwargs)
self._parent = self
self._unwrap_options(data.get('options', []))
@ -537,17 +534,21 @@ class SubCommand(SlashMixin):
if self.is_group():
raise TypeError('Cannot use a group')
options = [{
'type': self._type.value,
'name': self.name,
'options': self._parse_kwargs(kwargs),
}]
options = [
{
'type': self._type.value,
'name': self.name,
'options': self._parse_kwargs(kwargs),
}
]
for parent in self._walk_parents():
options = [{
'type': parent._type.value,
'name': parent.name,
'options': options,
}]
options = [
{
'type': parent._type.value,
'name': parent.name,
'options': options,
}
]
return await super().__call__(options, channel)

13
discord/components.py

@ -293,7 +293,7 @@ class SelectMenu(Component):
return {
'compontent_type': self.type.value,
'custom_id': self.custom_id,
'values': [option.value for option in options]
'values': [option.value for option in options],
}
async def choose(self, *options: SelectOption) -> Interaction:
@ -460,7 +460,7 @@ class TextInput(Component):
__repr_info__: ClassVar[Tuple[str, ...]] = __slots__
def __init__(self, data: TextInputPayload, _ = MISSING) -> None:
def __init__(self, data: TextInputPayload, _=MISSING) -> None:
self.type: ComponentType = ComponentType.text_input
self.style: TextStyle = try_enum(TextStyle, data['style'])
self.label: str = data['label']
@ -489,8 +489,13 @@ class TextInput(Component):
@value.setter
def value(self, value: Optional[str]) -> None:
length = len(value) if value is not None else 0
if (self.required or value is not None) and ((self.min_length is not None and length < self.min_length) or (self.max_length is not None and length > self.max_length)):
raise ValueError(f'value cannot be shorter than {self.min_length or 0} or longer than {self.max_length or "infinity"}')
if (self.required or value is not None) and (
(self.min_length is not None and length < self.min_length)
or (self.max_length is not None and length > self.max_length)
):
raise ValueError(
f'value cannot be shorter than {self.min_length or 0} or longer than {self.max_length or "infinity"}'
)
self._answer = value

54
discord/enums.py

@ -286,23 +286,23 @@ class ContentFilter(Enum, comparable=True):
class UserContentFilter(Enum):
always = 0
always = 0
on_interaction = 1
never = 2
never = 2
class StickerAnimationOptions(Enum):
disabled = 2
friends = 1
disabled = 2
friends = 1
all_messages = 0
class FriendFlags(Enum):
noone = 0
mutual_guilds = 1
mutual_friends = 2
noone = 0
mutual_guilds = 1
mutual_friends = 2
guild_and_friends = 3
everyone = 4
everyone = 4
def to_dict(self):
if self.value == 0:
@ -365,8 +365,8 @@ class DefaultAvatar(Enum):
class RelationshipType(Enum, comparable=True):
friend = 1
blocked = 2
friend = 1
blocked = 2
incoming_request = 3
outgoing_request = 4
@ -570,14 +570,14 @@ class ActivityType(Enum):
class HypeSquadHouse(Enum):
bravery = 1
bravery = 1
brilliance = 2
balance = 3
balance = 3
class PremiumType(Enum, comparable=True):
nitro_classic = 1
nitro = 2
nitro = 2
class TeamMembershipState(Enum):
@ -623,35 +623,35 @@ class StickerFormatType(Enum):
class ReportType(Enum):
illegal_content = 1
harassment = 2
phishing = 3
self_harm = 4
nsfw_content = 5
harassment = 2
phishing = 3
self_harm = 4
nsfw_content = 5
def __int__(self):
return self.value
class RelationshipAction(Enum):
send_friend_request = 'request'
unfriend = 'unfriend'
accept_request = 'accept'
deny_request = 'deny'
block = 'block'
unblock = 'unblock'
send_friend_request = 'request'
unfriend = 'unfriend'
accept_request = 'accept'
deny_request = 'deny'
block = 'block'
unblock = 'unblock'
remove_pending_request = 'remove'
class UnavailableGuildType(Enum):
existing = 'ready'
joined = 'joined'
joined = 'joined'
class RequiredActionType(Enum):
verify_phone = 'REQUIRE_VERIFIED_PHONE'
verify_email = 'REQUIRE_VERIFIED_EMAIL'
verify_phone = 'REQUIRE_VERIFIED_PHONE'
verify_email = 'REQUIRE_VERIFIED_EMAIL'
complete_captcha = 'REQUIRE_CAPTCHA'
accept_terms = 'AGREEMENTS'
accept_terms = 'AGREEMENTS'
class BrowserEnum(Enum):

10
discord/errors.py

@ -55,6 +55,7 @@ class DiscordException(Exception):
Ideally speaking, this could be caught to handle any exceptions raised from this library.
"""
pass
@ -63,11 +64,13 @@ class ClientException(DiscordException):
These are usually for exceptions that happened due to user input.
"""
pass
class GatewayNotFound(DiscordException):
"""An exception that is raised when the gateway for Discord could not be found"""
def __init__(self):
message = 'The gateway to connect to Discord was not found.'
super().__init__(message)
@ -109,6 +112,7 @@ class HTTPException(DiscordException):
json: :class:`dict`
The raw error JSON.
"""
def __init__(self, response: _ResponseType, message: Optional[Union[str, Dict[str, Any]]]):
self.response: _ResponseType = response
self.status: int = response.status # type: ignore - This attribute is filled by the library even if using requests
@ -141,6 +145,7 @@ class Forbidden(HTTPException):
Subclass of :exc:`HTTPException`
"""
pass
@ -149,6 +154,7 @@ class NotFound(HTTPException):
Subclass of :exc:`HTTPException`
"""
pass
@ -159,6 +165,7 @@ class DiscordServerError(HTTPException):
.. versionadded:: 1.5
"""
pass
@ -166,6 +173,7 @@ class InvalidData(ClientException):
"""Exception that's raised when the library encounters unknown
or invalid data from Discord.
"""
pass
@ -174,6 +182,7 @@ class AuthFailure(ClientException):
fails to log you in from improper credentials or some other misc.
failure.
"""
pass
@ -191,6 +200,7 @@ class ConnectionClosed(ClientException):
reason: :class:`str`
The reason provided for the closure.
"""
def __init__(self, socket: ClientWebSocketResponse, *, code: Optional[int] = None):
# This exception is just the same exception except
# reconfigured to subclass ClientException for users

4
discord/ext/commands/context.py

@ -415,4 +415,6 @@ class Context(discord.abc.Messageable, Generic[BotT]):
applications: bool = True,
application: Optional[discord.abc.Snowflake] = None,
):
return self.message.message_commands(query, limit=limit, command_ids=command_ids, applications=applications, application=application)
return self.message.message_commands(
query, limit=limit, command_ids=command_ids, applications=applications, application=application
)

42
discord/flags.py

@ -476,35 +476,35 @@ class PublicUserFlags(BaseFlags):
class PrivateUserFlags(PublicUserFlags):
r"""Wraps up the Discord User flags.
.. note::
These are only available on your own user flags.
.. note::
These are only available on your own user flags.
.. container:: operations
.. container:: operations
.. describe:: x == y
.. describe:: x == y
Checks if two UserFlags are equal.
.. describe:: x != y
Checks if two UserFlags are equal.
.. describe:: x != y
Checks if two UserFlags are not equal.
.. describe:: hash(x)
Checks if two UserFlags are not equal.
.. describe:: hash(x)
Return the flag's hash.
.. describe:: iter(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.
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
-----------
value: :class:`int`
The raw value. This value is a bit array field of a 53-bit integer
representing the currently available flags. You should query
flags via the properties rather than using this raw value.
"""
Attributes
-----------
value: :class:`int`
The raw value. This value is a bit array field of a 53-bit integer
representing the currently available flags. You should query
flags via the properties rather than using this raw value.
"""
__slots__ = ()

55
discord/gateway.py

@ -61,6 +61,7 @@ if TYPE_CHECKING:
class ReconnectWebSocket(Exception):
"""Signals to safely reconnect the websocket."""
def __init__(self, *, resume: bool = True):
self.resume = resume
self.op: str = 'RESUME' if resume else 'IDENTIFY'
@ -433,20 +434,15 @@ class DiscordWebSocket:
'token': self.token,
'capabilities': 253,
'properties': self._super_properties,
'presence': {
'status': 'online',
'since': 0,
'activities': [],
'afk': False
},
'presence': {'status': 'online', 'since': 0, 'activities': [], 'afk': False},
'compress': False,
'client_state': {
'guild_hashes': {},
'highest_last_message_id': '0',
'read_state_version': 0,
'user_guild_settings_version': -1
}
}
'user_guild_settings_version': -1,
},
},
}
if not self._zlib_enabled:
@ -543,14 +539,12 @@ class DiscordWebSocket:
self._trace = trace = data.get('_trace', [])
self.sequence = msg['s']
self.session_id = data['session_id']
_log.info('Connected to Gateway: %s (Session ID: %s).',
', '.join(trace), self.session_id)
_log.info('Connected to Gateway: %s (Session ID: %s).', ', '.join(trace), self.session_id)
await self.voice_state() # Initial OP 4
elif event == 'RESUMED':
self._trace = trace = data.get('_trace', [])
_log.info('Gateway has successfully RESUMED session %s under trace %s.',
self.session_id, ', '.join(trace))
_log.info('Gateway has successfully RESUMED session %s under trace %s.', self.session_id, ', '.join(trace))
try:
func = self._discord_parsers[event]
@ -663,7 +657,7 @@ class DiscordWebSocket:
activities: Optional[List[BaseActivity]] = None,
status: Optional[str] = None,
since: float = 0.0,
afk: bool = False
afk: bool = False,
) -> None:
if activities is not None:
if not all(isinstance(activity, BaseActivity) for activity in activities):
@ -675,26 +669,20 @@ class DiscordWebSocket:
if status == 'idle':
since = int(time.time() * 1000)
payload = {
'op': self.PRESENCE,
'd': {
'activities': activities,
'afk': afk,
'since': since,
'status': str(status)
}
}
payload = {'op': self.PRESENCE, 'd': {'activities': activities, 'afk': afk, 'since': since, 'status': str(status)}}
sent = utils._to_json(payload)
_log.debug('Sending "%s" to change presence.', sent)
await self.send(sent)
async def request_lazy_guild(self, guild_id, *, typing=None, threads=None, activities=None, members=None, channels=None, thread_member_lists=None):
async def request_lazy_guild(
self, guild_id, *, typing=None, threads=None, activities=None, members=None, channels=None, thread_member_lists=None
):
payload = {
'op': self.GUILD_SUBSCRIBE,
'd': {
'guild_id': str(guild_id),
}
},
}
data = payload['d']
@ -732,7 +720,7 @@ class DiscordWebSocket:
'limit': limit,
'presences': presences,
'user_ids': user_ids,
}
},
}
if nonce:
@ -758,7 +746,7 @@ class DiscordWebSocket:
'self_mute': self_mute,
'self_deaf': self_deaf,
'self_video': self_video,
}
},
}
if preferred_region is not None:
@ -768,12 +756,7 @@ class DiscordWebSocket:
await self.send_as_json(payload)
async def access_dm(self, channel_id: int):
payload = {
'op': self.CALL_CONNECT,
'd': {
'channel_id': str(channel_id)
}
}
payload = {'op': self.CALL_CONNECT, 'd': {'channel_id': str(channel_id)}}
_log.debug('Sending ACCESS_DM for channel %s.', channel_id)
await self.send_as_json(payload)
@ -796,7 +779,7 @@ class DiscordWebSocket:
'd': {
'guild_id': guild_id,
'type': type,
}
},
}
if nonce is not None:
@ -1014,8 +997,8 @@ class DiscordVoiceWebSocket:
else:
ssrc.speaking = speaking
#item = state.guild or state._state
#item._update_speaking_status(user_id, speaking)
# item = state.guild or state._state
# item._update_speaking_status(user_id, speaking)
await self._hook(self, msg)

8
discord/guild.py

@ -3479,7 +3479,7 @@ class Guild(Hashable):
.. versionadded:: 2.0
.. note::
If you are the owner, have either of :attr:`Permissions.adminstrator`,
If you are the owner, have either of :attr:`Permissions.adminstrator`,
:attr:`Permission.kick_members`, :attr:`Permission.ban_members`, or :attr:`Permission.manage_roles`,
permissions will be fetched through OPcode 8 (this includes offline members).
Else, they will be scraped from the member sidebar.
@ -3511,7 +3511,9 @@ class Guild(Hashable):
if self._state.is_guild_evicted(self):
raise ClientException('This guild is no longer available.')
members = await self._state.scrape_guild(self, cache=cache, force_scraping=force_scraping, delay=delay, channels=channels)
members = await self._state.scrape_guild(
self, cache=cache, force_scraping=force_scraping, delay=delay, channels=channels
)
if members is None:
raise ClientException('Fetching members failed')
return members # type: ignore
@ -3602,7 +3604,7 @@ class Guild(Hashable):
self_mute: bool = False,
self_deaf: bool = False,
self_video: bool = False,
preferred_region: Optional[str] = MISSING
preferred_region: Optional[str] = MISSING,
) -> None:
"""|coro|

1
discord/guild_folder.py

@ -57,6 +57,7 @@ class GuildFolder:
guilds: List[:class:`Guild`]
The guilds in the folder.
"""
__slots__ = ('_state', 'id', 'name', '_colour', 'guilds')
def __init__(self, *, data, state: ConnectionState) -> None:

307
discord/http.py

@ -374,12 +374,14 @@ class HTTPClient:
'release_channel': 'stable',
'system_locale': 'en-US',
'client_build_number': bn,
'client_event_source': None
'client_event_source': None,
}
self.encoded_super_properties = b64encode(json.dumps(sp).encode()).decode('utf-8')
self._started = True
async def ws_connect(self, url: str, *, compress: int = 0, host: Optional[str] = None) -> aiohttp.ClientWebSocketResponse:
async def ws_connect(
self, url: str, *, compress: int = 0, host: Optional[str] = None
) -> aiohttp.ClientWebSocketResponse:
if not host:
host = url[6:].split('?')[0].rstrip('/') # Removes 'wss://' and the query params
@ -430,7 +432,9 @@ class HTTPClient:
'Origin': 'https://discord.com',
'Pragma': 'no-cache',
'Referer': 'https://discord.com/channels/@me',
'Sec-CH-UA': '"Google Chrome";v="{0}", "Chromium";v="{0}", ";Not A Brand";v="99"'.format(self.browser_version.split('.')[0]),
'Sec-CH-UA': '"Google Chrome";v="{0}", "Chromium";v="{0}", ";Not A Brand";v="99"'.format(
self.browser_version.split('.')[0]
),
'Sec-CH-UA-Mobile': '?0',
'Sec-CH-UA-Platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
@ -439,7 +443,7 @@ class HTTPClient:
'User-Agent': self.user_agent,
'X-Discord-Locale': 'en-US',
'X-Debug-Options': 'bugReporterEnabled',
'X-Super-Properties': self.encoded_super_properties
'X-Super-Properties': self.encoded_super_properties,
}
# Header modification
@ -596,9 +600,7 @@ class HTTPClient:
self.ack_token = None
def get_me(self, with_analytics_token=True) -> Response[user.User]:
params = {
'with_analytics_token': str(with_analytics_token).lower()
}
params = {'with_analytics_token': str(with_analytics_token).lower()}
return self.request(Route('GET', '/users/@me'), params=params)
async def static_login(self, token: str) -> user.User:
@ -673,32 +675,21 @@ class HTTPClient:
def send_typing(self, channel_id: Snowflake) -> Response[None]:
return self.request(Route('POST', '/channels/{channel_id}/typing', channel_id=channel_id))
async def ack_message(
self, channel_id: Snowflake, message_id: Snowflake
): # TODO: response type (simple)
async def ack_message(self, channel_id: Snowflake, message_id: Snowflake): # TODO: response type (simple)
r = Route('POST', '/channels/{channel_id}/messages/{message_id}/ack', channel_id=channel_id, message_id=message_id)
payload = {
'token': self.ack_token
}
payload = {'token': self.ack_token}
data = await self.request(r, json=payload)
self.ack_token = data['token']
def unack_message(
self, channel_id: Snowflake, message_id: Snowflake, *, mention_count: int = 0
) -> Response[None]:
def unack_message(self, channel_id: Snowflake, message_id: Snowflake, *, mention_count: int = 0) -> Response[None]:
r = Route('POST', '/channels/{channel_id}/messages/{message_id}/ack', channel_id=channel_id, message_id=message_id)
payload = {
'manual': True,
'mention_count': mention_count
}
payload = {'manual': True, 'mention_count': mention_count}
return self.request(r, json=payload)
def ack_messages(self, read_states) -> Response[None]: # TODO: type and implement
payload = {
'read_states': read_states
}
payload = {'read_states': read_states}
return self.request(Route('POST', '/read-states/ack-bulk'), json=payload)
@ -916,7 +907,9 @@ class HTTPClient:
r = Route('PATCH', '/guilds/{guild_id}/voice-states/@me', guild_id=guild_id)
return self.request(r, json=payload)
def edit_voice_state(self, guild_id: Snowflake, user_id: Snowflake, payload: Dict[str, Any]) -> Response[None]: # TODO: remove payload
def edit_voice_state(
self, guild_id: Snowflake, user_id: Snowflake, payload: Dict[str, Any]
) -> Response[None]: # TODO: remove payload
r = Route('PATCH', '/guilds/{guild_id}/voice-states/{user_id}', guild_id=guild_id, user_id=user_id)
return self.request(r, json=payload)
@ -935,10 +928,12 @@ class HTTPClient:
r = Route('PATCH', '/guilds/{guild_id}/members/@me', guild_id=guild_id)
payload['avatar'] = avatar
else:
r = choice((
Route('PATCH', '/guilds/{guild_id}/members/@me/nick', guild_id=guild_id),
Route('PATCH', '/guilds/{guild_id}/members/@me', guild_id=guild_id)
))
r = choice(
(
Route('PATCH', '/guilds/{guild_id}/members/@me/nick', guild_id=guild_id),
Route('PATCH', '/guilds/{guild_id}/members/@me', guild_id=guild_id),
)
)
return self.request(r, json=payload, reason=reason)
@ -1024,9 +1019,7 @@ class HTTPClient:
return self.request(Route('POST', '/guilds/{guild_id}/channels', guild_id=guild_id), json=payload, reason=reason)
def delete_channel(
self, channel_id: Snowflake, *, reason: Optional[str] = None
) -> Response[None]:
def delete_channel(self, channel_id: Snowflake, *, reason: Optional[str] = None) -> Response[None]:
return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id), reason=reason)
# Thread management
@ -1085,29 +1078,25 @@ class HTTPClient:
def join_thread(self, channel_id: Snowflake) -> Response[None]:
r = Route('POST', '/channels/{channel_id}/thread-members/@me', channel_id=channel_id)
params = {
'location': choice(('Banner', 'Toolbar Overflow', 'Context Menu'))
}
params = {'location': choice(('Banner', 'Toolbar Overflow', 'Context Menu'))}
return self.request(r, params=params)
def add_user_to_thread(self, channel_id: Snowflake, user_id: Snowflake) -> Response[None]: # TODO: Find a way to test private thread stuff
def add_user_to_thread(
self, channel_id: Snowflake, user_id: Snowflake
) -> Response[None]: # TODO: Find a way to test private thread stuff
r = Route('PUT', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id)
return self.request(r)
def leave_thread(self, channel_id: Snowflake) -> Response[None]:
r = Route('DELETE', '/channels/{channel_id}/thread-members/@me', channel_id=channel_id)
params = {
'location': choice(('Toolbar Overflow', 'Context Menu'))
}
params = {'location': choice(('Toolbar Overflow', 'Context Menu'))}
return self.request(r, params=params)
def remove_user_from_thread(self, channel_id: Snowflake, user_id: Snowflake) -> Response[None]:
r = Route('DELETE', '/channels/{channel_id}/thread-members/{user_id}', channel_id=channel_id, user_id=user_id)
params = {
'location': 'Context Menu'
}
params = {'location': 'Context Menu'}
return self.request(r, params=params)
@ -1190,24 +1179,18 @@ class HTTPClient:
# Guild management
def get_guilds(self, with_counts: bool = True) -> Response[List[guild.Guild]]:
params = {
'with_counts': str(with_counts).lower()
}
params = {'with_counts': str(with_counts).lower()}
return self.request(Route('GET', '/users/@me/guilds'), params=params, super_properties_to_track=True)
def leave_guild(self, guild_id: Snowflake, lurking: bool = False) -> Response[None]:
r = Route('DELETE', '/users/@me/guilds/{guild_id}', guild_id=guild_id)
payload = {
'lurking': lurking
}
payload = {'lurking': lurking}
return self.request(r, json=payload)
def get_guild(self, guild_id: Snowflake, with_counts: bool = True) -> Response[guild.Guild]:
params = {
'with_counts': str(with_counts).lower()
}
params = {'with_counts': str(with_counts).lower()}
return self.request(Route('GET', '/guilds/{guild_id}', guild_id=guild_id), params=params)
@ -1225,7 +1208,7 @@ class HTTPClient:
'icon': icon,
'system_channel_id': None,
'channels': [],
'guild_template_code': template # API go brrr
'guild_template_code': template, # API go brrr
}
return self.request(Route('POST', '/guilds'), json=payload)
@ -1302,9 +1285,7 @@ class HTTPClient:
return self.request(Route('GET', '/guilds/{guild_id}/vanity-url', guild_id=guild_id))
def change_vanity_code(self, guild_id: Snowflake, code: str, *, reason: Optional[str] = None) -> Response[None]:
payload = {
'code': code
}
payload = {'code': code}
return self.request(Route('PATCH', '/guilds/{guild_id}/vanity-url', guild_id=guild_id), json=payload, reason=reason)
@ -1483,7 +1464,9 @@ class HTTPClient:
return self.request(Route('GET', '/guilds/{guild_id}/member-verification', guild_id=guild_id), params=params)
def accept_member_verification(self, guild_id: Snowflake, **payload) -> Response[None]: # payload is the same as the above return type
def accept_member_verification(
self, guild_id: Snowflake, **payload
) -> Response[None]: # payload is the same as the above return type
return self.request(Route('PUT', '/guilds/{guild_id}/requests/@me', guild_id=guild_id), json=payload)
def get_all_integrations(
@ -1535,9 +1518,7 @@ class HTTPClient:
action_type: Optional[AuditLogAction] = None,
) -> Response[audit_log.AuditLog]:
r = Route('GET', '/guilds/{guild_id}/audit-logs', guild_id=guild_id)
params: Dict[str, Any] = {
'limit': limit
}
params: Dict[str, Any] = {'limit': limit}
if before:
params['before'] = before
if after:
@ -1578,15 +1559,23 @@ class HTTPClient:
guild_id=getattr(message.guild, 'id', None),
channel_id=message.channel.id,
channel_type=getattr(message.channel, 'type', None),
message_id=message.id
message_id=message.id,
)
elif type is InviteType.guild or type is InviteType.group_dm: # Join Guild, Accept Invite Page
props = choice((
ContextProperties._from_accept_invite_page(guild_id=guild_id, channel_id=channel_id, channel_type=channel_type),
ContextProperties._from_join_guild_popup(guild_id=guild_id, channel_id=channel_id, channel_type=channel_type)
))
props = choice(
(
ContextProperties._from_accept_invite_page(
guild_id=guild_id, channel_id=channel_id, channel_type=channel_type
),
ContextProperties._from_join_guild_popup(
guild_id=guild_id, channel_id=channel_id, channel_type=channel_type
),
)
)
else: # Accept Invite Page
props = ContextProperties._from_accept_invite_page(guild_id=guild_id, channel_id=channel_id, channel_type=channel_type)
props = ContextProperties._from_accept_invite_page(
guild_id=guild_id, channel_id=channel_id, channel_type=channel_type
)
return self.request(Route('POST', '/invites/{invite_id}', invite_id=invite_id), context_properties=props, json={})
def create_invite(
@ -1751,24 +1740,18 @@ class HTTPClient:
return self.edit_member(guild_id=guild_id, user_id=user_id, channel_id=channel_id, reason=reason)
def ring(self, channel_id: Snowflake, *recipients: Snowflake) -> Response[None]:
payload = {
'recipients': recipients or None
}
payload = {'recipients': recipients or None}
return self.request(Route('POST', '/channels/{channel_id}/call/ring', channel_id=channel_id), json=payload)
def stop_ringing(self, channel_id: Snowflake, *recipients: Snowflake) -> Response[None]:
r = Route('POST', '/channels/{channel_id}/call/stop-ringing', channel_id=channel_id)
payload = {
'recipients': recipients
}
payload = {'recipients': recipients}
return self.request(r, json=payload)
def change_call_voice_region(self, channel_id: int, voice_region: str): # TODO: return type
payload = {
'region': voice_region
}
payload = {'region': voice_region}
return self.request(Route('PATCH', '/channels/{channel_id}/call', channel_id=channel_id), json=payload)
@ -1997,51 +1980,65 @@ class HTTPClient:
def remove_relationship(self, user_id: Snowflake, *, action: RelationshipAction) -> Response[None]:
r = Route('DELETE', '/users/@me/relationships/{user_id}', user_id=user_id)
if action is RelationshipAction.deny_request: # User Profile, Friends, DM Channel
props = choice((
ContextProperties._from_friends_page(), ContextProperties._from_user_profile(),
ContextProperties._from_dm_channel()
))
props = choice(
(
ContextProperties._from_friends_page(),
ContextProperties._from_user_profile(),
ContextProperties._from_dm_channel(),
)
)
elif action is RelationshipAction.unfriend: # Friends, ContextMenu, User Profile, DM Channel
props = choice((
ContextProperties._from_context_menu(), ContextProperties._from_user_profile(),
ContextProperties._from_friends_page(), ContextProperties._from_dm_channel()
))
props = choice(
(
ContextProperties._from_context_menu(),
ContextProperties._from_user_profile(),
ContextProperties._from_friends_page(),
ContextProperties._from_dm_channel(),
)
)
elif action == RelationshipAction.unblock: # Friends, ContextMenu, User Profile, DM Channel, NONE
props = choice((
ContextProperties._from_context_menu(), ContextProperties._from_user_profile(),
ContextProperties._from_friends_page(), ContextProperties._from_dm_channel(), None
))
elif action == RelationshipAction.remove_pending_request: # Friends
props = choice(
(
ContextProperties._from_context_menu(),
ContextProperties._from_user_profile(),
ContextProperties._from_friends_page(),
ContextProperties._from_dm_channel(),
None,
)
)
elif action == RelationshipAction.remove_pending_request: # Friends
props = ContextProperties._from_friends_page()
return self.request(r, context_properties=props) # type: ignore
def add_relationship(
self, user_id: Snowflake, type: int = MISSING, *, action: RelationshipAction
): # TODO: return type
def add_relationship(self, user_id: Snowflake, type: int = MISSING, *, action: RelationshipAction): # TODO: return type
r = Route('PUT', '/users/@me/relationships/{user_id}', user_id=user_id)
if action is RelationshipAction.accept_request: # User Profile, Friends, DM Channel
props = choice((
ContextProperties._from_friends_page(),
ContextProperties._from_user_profile(),
ContextProperties._from_dm_channel()
))
props = choice(
(
ContextProperties._from_friends_page(),
ContextProperties._from_user_profile(),
ContextProperties._from_dm_channel(),
)
)
elif action is RelationshipAction.block: # Friends, ContextMenu, User Profile, DM Channel.
props = choice((
ContextProperties._from_context_menu(),
ContextProperties._from_user_profile(),
ContextProperties._from_friends_page(),
ContextProperties._from_dm_channel()
))
props = choice(
(
ContextProperties._from_context_menu(),
ContextProperties._from_user_profile(),
ContextProperties._from_friends_page(),
ContextProperties._from_dm_channel(),
)
)
elif action is RelationshipAction.send_friend_request: # ContextMenu, User Profile, DM Channel
props = choice((
ContextProperties._from_context_menu(),
ContextProperties._from_user_profile(),
ContextProperties._from_dm_channel()
))
kwargs = {
'context_properties': props # type: ignore
}
props = choice(
(
ContextProperties._from_context_menu(),
ContextProperties._from_user_profile(),
ContextProperties._from_dm_channel(),
)
)
kwargs = {'context_properties': props} # type: ignore
if type:
kwargs['json'] = {'type': type}
@ -2049,21 +2046,13 @@ class HTTPClient:
def send_friend_request(self, username, discriminator): # TODO: return type
r = Route('POST', '/users/@me/relationships')
props = choice(( # Friends, Group DM
ContextProperties._from_add_friend_page,
ContextProperties._from_group_dm
))
payload = {
'username': username,
'discriminator': int(discriminator)
}
props = choice((ContextProperties._from_add_friend_page, ContextProperties._from_group_dm)) # Friends, Group DM
payload = {'username': username, 'discriminator': int(discriminator)}
return self.request(r, json=payload, context_properties=props)
def change_friend_nickname(self, user_id, nickname):
payload = {
'nickname': nickname
}
payload = {'nickname': nickname}
return self.request(Route('PATCH', '/users/@me/relationships/{user_id}', user_id=user_id), json=payload)
@ -2083,10 +2072,10 @@ class HTTPClient:
def get_user(self, user_id: Snowflake) -> Response[user.User]:
return self.request(Route('GET', '/users/{user_id}', user_id=user_id))
def get_user_profile(self, user_id: Snowflake, guild_id: Snowflake = MISSING, *, with_mutual_guilds: bool = True): # TODO: return type
params: Dict[str, Any] = {
'with_mutual_guilds': str(with_mutual_guilds).lower()
}
def get_user_profile(
self, user_id: Snowflake, guild_id: Snowflake = MISSING, *, with_mutual_guilds: bool = True
): # TODO: return type
params: Dict[str, Any] = {'with_mutual_guilds': str(with_mutual_guilds).lower()}
if guild_id is not MISSING:
params['guild_id'] = guild_id
@ -2102,16 +2091,12 @@ class HTTPClient:
return self.request(Route('GET', '/users/@me/notes/{user_id}', user_id=user_id))
def set_note(self, user_id: Snowflake, *, note: Optional[str] = None) -> Response[None]:
payload = {
'note': note or ''
}
payload = {'note': note or ''}
return self.request(Route('PUT', '/users/@me/notes/{user_id}', user_id=user_id), json=payload)
def change_hypesquad_house(self, house_id: int) -> Response[None]:
payload = {
'house_id': house_id
}
payload = {'house_id': house_id}
return self.request(Route('POST', '/hypesquad/online'), json=payload)
@ -2124,7 +2109,7 @@ class HTTPClient:
def edit_settings(self, **payload): # TODO: return type, is this cheating?
return self.request(Route('PATCH', '/users/@me/settings'), json=payload)
def get_tracking(self): # TODO: return type
def get_tracking(self): # TODO: return type
return self.request(Route('GET', '/users/@me/consent'))
def edit_tracking(self, payload):
@ -2143,9 +2128,7 @@ class HTTPClient:
return self.request(Route('GET', '/users/@me/connections/{type}/{id}/access-token', type=type, id=id))
def get_my_applications(self, *, with_team_applications: bool = True) -> Response[List[appinfo.AppInfo]]:
params = {
'with_team_applications': str(with_team_applications).lower()
}
params = {'with_team_applications': str(with_team_applications).lower()}
return self.request(Route('GET', '/applications'), params=params, super_properties_to_track=True)
@ -2153,25 +2136,25 @@ class HTTPClient:
return self.request(Route('GET', '/applications/{app_id}', app_id=app_id), super_properties_to_track=True)
def edit_application(self, app_id: Snowflake, payload) -> Response[appinfo.AppInfo]:
return self.request(Route('PATCH', '/applications/{app_id}', app_id=app_id), super_properties_to_track=True, json=payload)
return self.request(
Route('PATCH', '/applications/{app_id}', app_id=app_id), super_properties_to_track=True, json=payload
)
def delete_application(self, app_id: Snowflake) -> Response[None]:
return self.request(Route('POST', '/applications/{app_id}/delete', app_id=app_id), super_properties_to_track=True)
def transfer_application(self, app_id: Snowflake, team_id: Snowflake) -> Response[appinfo.AppInfo]:
payload = {
'team_id': team_id
}
payload = {'team_id': team_id}
return self.request(Route('POST', '/applications/{app_id}/transfer', app_id=app_id), json=payload, super_properties_to_track=True)
return self.request(
Route('POST', '/applications/{app_id}/transfer', app_id=app_id), json=payload, super_properties_to_track=True
)
def get_partial_application(self, app_id: Snowflake) -> Response[appinfo.PartialAppInfo]:
return self.request(Route('GET', '/applications/{app_id}/rpc', app_id=app_id))
return self.request(Route('GET', '/oauth2/applications/{app_id}/rpc', app_id=app_id))
def create_app(self, name: str):
payload = {
'name': name
}
payload = {'name': name}
return self.request(Route('POST', '/applications'), json=payload, super_properties_to_track=True)
@ -2183,20 +2166,17 @@ class HTTPClient:
self, app_id: Snowflake, *, localize: bool = False, with_bundled_skus: bool = True
): # TODO: return type
r = Route('GET', '/applications/{app_id}/skus', app_id=app_id)
params = {
'localize': str(localize).lower(),
'with_bundled_skus': str(with_bundled_skus).lower()
}
params = {'localize': str(localize).lower(), 'with_bundled_skus': str(with_bundled_skus).lower()}
return self.request(r, params=params, super_properties_to_track=True)
def get_app_whitelist(self, app_id):
return self.request(Route('GET', '/oauth2/applications/{app_id}/allowlist', app_id=app_id), super_properties_to_track=True)
return self.request(
Route('GET', '/oauth2/applications/{app_id}/allowlist', app_id=app_id), super_properties_to_track=True
)
def create_team(self, name: str):
payload = {
'name': name
}
payload = {'name': name}
return self.request(Route('POST', '/teams'), json=payload, super_properties_to_track=True)
@ -2207,7 +2187,9 @@ class HTTPClient:
return self.request(Route('GET', '/teams/{team_id}', team_id=team_id), super_properties_to_track=True)
def edit_team(self, team_id: Snowflake, payload) -> Response[team.Team]:
return self.request(Route('PATCH', '/teams/{team_id}', team_id=team_id), json=payload, super_properties_to_track=True)
return self.request(
Route('PATCH', '/teams/{team_id}', team_id=team_id), json=payload, super_properties_to_track=True
)
def delete_team(self, team_id: Snowflake) -> Response[None]:
return self.request(Route('POST', '/teams/{app_id}/delete', team_id=team_id), super_properties_to_track=True)
@ -2219,15 +2201,17 @@ 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)}
return self.request(Route('POST', '/teams/{team_id}/members', team_id=team_id), json=payload, super_properties_to_track=True)
return self.request(
Route('POST', '/teams/{team_id}/members', team_id=team_id), json=payload, super_properties_to_track=True
)
def remove_team_member(self, team_id: Snowflake, user_id: Snowflake):
return self.request(Route('DELETE', '/teams/{team_id}/members/{user_id}', team_id=team_id, user_id=user_id), super_properties_to_track=True)
return self.request(
Route('DELETE', '/teams/{team_id}/members/{user_id}', team_id=team_id, user_id=user_id),
super_properties_to_track=True,
)
def botify_app(self, app_id: Snowflake):
return self.request(Route('POST', '/applications/{app_id}/bot', app_id=app_id), super_properties_to_track=True)
@ -2241,12 +2225,7 @@ class HTTPClient:
def mobile_report( # Report v1
self, guild_id: Snowflake, channel_id: Snowflake, message_id: Snowflake, reason: str
): # TODO: return type
payload = {
'guild_id': guild_id,
'channel_id': channel_id,
'message_id': message_id,
'reason': reason
}
payload = {'guild_id': guild_id, 'channel_id': channel_id, 'message_id': message_id, 'reason': reason}
return self.request(Route('POST', '/report'), json=payload)
@ -2262,7 +2241,7 @@ class HTTPClient:
*,
form_data: bool = False,
nonce: Optional[str] = MISSING,
application_id: Snowflake = MISSING
application_id: Snowflake = MISSING,
) -> Response[None]:
state = getattr(message, '_state', channel._state)
payload = {

7
discord/interactions.py

@ -118,9 +118,7 @@ class Interaction:
return cls(int(id), type, nonce, user=user, name=name, state=user._state, channel=channel)
@classmethod
def _from_message(
cls, message: Message, *, id: Snowflake, type: int, user: UserPayload, **data
) -> Interaction:
def _from_message(cls, message: Message, *, id: Snowflake, type: int, user: UserPayload, **data) -> Interaction:
state = message._state
name = data.get('name')
user_cls = state.store_user(user)
@ -142,6 +140,7 @@ class Interaction:
"""Optional[:class:`Message`]: Returns the message that is the response to this interaction.
May not exist or be cached.
"""
def predicate(message: Message) -> bool:
return message.interaction is not None and message.interaction.id == self.id
@ -154,7 +153,7 @@ class Interaction:
@cached_slot_property('_cs_channel')
def channel(self) -> MessageableChannel:
"""Union[:class:`TextChannel`, :class:`Thread`, :class:`DMChannel`, :class:`GroupChannel`]:
"""Union[:class:`TextChannel`, :class:`Thread`, :class:`DMChannel`, :class:`GroupChannel`]:
Returns the channel this interaction originated from.
"""
return getattr(self.message, 'channel', None)

6
discord/invite.py

@ -399,6 +399,7 @@ class Invite(Hashable):
application = data.get('target_application')
if application is not None:
from .appinfo import PartialApplication
application = PartialApplication(data=application, state=state)
self.target_application: Optional[PartialApplication] = application
@ -552,7 +553,7 @@ class Invite(Hashable):
"""
state = self._state
type = self.type
if (message := self._message):
if message := self._message:
kwargs = {'message': message}
else:
kwargs = {
@ -563,12 +564,15 @@ class Invite(Hashable):
data = await state.http.accept_invite(self.code, type, **kwargs)
if type is InviteType.guild:
from .guild import Guild
return Guild(data=data['guild'], state=state)
elif type is InviteType.group_dm:
from .channel import GroupChannel
return GroupChannel(data=data['channel'], state=state, me=state.user) # type: ignore
else:
from .user import User
return User(data=data['inviter'], state=state)
async def accept(self) -> Union[Guild, User, GroupChannel]:

9
discord/iterators.py

@ -52,7 +52,6 @@ _Func = Callable[[T], Union[OT, Awaitable[OT]]]
OLDEST_OBJECT = Object(id=0)
def _is_fake(item: Union[Messageable, Message]) -> bool: # I hate this too, but <circular imports> and performance exist
try:
item.guild # type: ignore
@ -127,11 +126,11 @@ class CommandIterator:
}
if self.applications:
kwargs['applications'] = True # Only sent if it's True...
if (app := self.application):
if app := self.application:
kwargs['application'] = app.id
if (query := self.query) is not None:
kwargs['query'] = query
if (cmds := self.command_ids):
if cmds := self.command_ids:
kwargs['command_ids'] = cmds
self.kwargs = kwargs
@ -173,7 +172,9 @@ class CommandIterator:
for _ in range(3):
await state.ws.request_commands(**kwargs, limit=retrieve, nonce=nonce)
try:
data: Optional[Dict[str, Any]] = await asyncio.wait_for(state.ws.wait_for('guild_application_commands_update', predicate), timeout=3)
data: Optional[Dict[str, Any]] = await asyncio.wait_for(
state.ws.wait_for('guild_application_commands_update', predicate), timeout=3
)
except asyncio.TimeoutError:
pass

2
discord/message.py

@ -385,7 +385,7 @@ class DeletedReferencedMessage:
def id(self) -> int:
""":class:`int`: The message ID of the deleted referenced message."""
# The parent's message id won't be None here
return self._parent.message_id # type: ignore
return self._parent.message_id # type: ignore
@property
def channel_id(self) -> int:

5
discord/modal.py

@ -62,6 +62,7 @@ class Modal:
application: :class:`InteractionApplication`
The application that sent the modal.
"""
__slots__ = ('_state', 'interaction', 'id', 'nonce', 'title', 'custom_id', 'components', 'application')
def __init__(self, *, data: dict, interaction: Interaction):
@ -110,7 +111,9 @@ class Modal:
state._interaction_cache[nonce] = (int(type), None, interaction.channel)
try:
await state.http.interact(type, self.to_dict(), interaction.channel, nonce=nonce, application_id=self.application.id)
await state.http.interact(
type, self.to_dict(), interaction.channel, nonce=nonce, application_id=self.application.id
)
i = await state.client.wait_for(
'interaction_finish',
check=lambda d: d.nonce == nonce,

6
discord/profile.py

@ -99,7 +99,9 @@ class Profile:
self.premium_since: Optional[datetime] = utils.parse_time(data['premium_since'])
self.boosting_since: Optional[datetime] = utils.parse_time(data['premium_guild_since'])
self.connections: List[PartialConnection] = [PartialConnection(d) for d in data['connected_accounts']] # TODO: parse these
self.connections: List[PartialConnection] = [
PartialConnection(d) for d in data['connected_accounts']
]
self.mutual_guilds: Optional[List[Guild]] = self._parse_mutual_guilds(data.get('mutual_guilds'))
self.mutual_friends: Optional[List[User]] = self._parse_mutual_friends(data.get('mutual_friends'))
@ -151,12 +153,14 @@ class Profile:
class UserProfile(Profile, User):
"""Represents a Discord user's profile. This is a :class:`User` with extended attributes."""
def __repr__(self) -> str:
return f'<UserProfile id={self.id} name={self.name!r} discriminator={self.discriminator!r} bot={self.bot} system={self.system} premium={self.premium}>'
class MemberProfile(Profile, Member):
"""Represents a Discord member's profile. This is a :class:`Member` with extended attributes."""
def __repr__(self) -> str:
return (
f'<MemberProfile id={self._user.id} name={self._user.name!r} discriminator={self._user.discriminator!r}'

24
discord/settings.py

@ -28,7 +28,16 @@ from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, TYPE_CHECKING
from .activity import create_settings_activity
from .enums import FriendFlags, Locale, NotificationLevel, Status, StickerAnimationOptions, Theme, UserContentFilter, try_enum
from .enums import (
FriendFlags,
Locale,
NotificationLevel,
Status,
StickerAnimationOptions,
Theme,
UserContentFilter,
try_enum,
)
from .guild_folder import GuildFolder
from .utils import MISSING, parse_time, utcnow
@ -385,7 +394,8 @@ class ChannelSettings:
guild = self._state._get_guild(self._guild_id)
return guild and guild.get_channel(self._channel_id)
async def edit(self,
async def edit(
self,
*,
muted: bool = MISSING,
duration: Optional[int] = MISSING,
@ -433,7 +443,7 @@ class ChannelSettings:
if duration is not None:
mute_config = {
'selected_time_window': duration * 3600,
'end_time': (datetime.utcnow() + timedelta(hours=duration)).isoformat()
'end_time': (datetime.utcnow() + timedelta(hours=duration)).isoformat(),
}
payload['mute_config'] = mute_config
@ -448,11 +458,7 @@ class ChannelSettings:
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
@ -558,7 +564,7 @@ class GuildSettings:
if duration is not None:
mute_config = {
'selected_time_window': duration * 3600,
'end_time': (datetime.utcnow() + timedelta(hours=duration)).isoformat()
'end_time': (datetime.utcnow() + timedelta(hours=duration)).isoformat(),
}
payload['mute_config'] = mute_config

66
discord/state.py

@ -244,7 +244,11 @@ class MemberSidebar:
guild = self.guild
ret = set()
channels = [channel for channel in self.guild.channels if channel.type != ChannelType.stage_voice and channel.permissions_for(guild.me).read_messages]
channels = [
channel
for channel in self.guild.channels
if channel.type != ChannelType.stage_voice and channel.permissions_for(guild.me).read_messages
]
if guild.rules_channel is not None:
channels.insert(0, guild.rules_channel)
@ -693,7 +697,11 @@ class ConnectionState:
self._private_channels_by_user.pop(recipient.id, None)
def _get_message(self, msg_id: Optional[int]) -> Optional[Message]:
return utils.find(lambda m: m.id == msg_id, reversed(self._messages)) if self._messages else utils.find(lambda m: m.id == msg_id, reversed(self._call_message_cache.values()))
return (
utils.find(lambda m: m.id == msg_id, reversed(self._messages))
if self._messages
else utils.find(lambda m: m.id == msg_id, reversed(self._call_message_cache.values()))
)
def _add_guild_from_data(self, data: GuildPayload, *, from_ready: bool = False) -> Optional[Guild]:
guild_id = int(data['id'])
@ -809,7 +817,7 @@ class ConnectionState:
extra_data.get('guilds', []),
extra_data.get('merged_members', []),
data.get('merged_members', []),
extra_data['merged_presences'].get('guilds', [])
extra_data['merged_presences'].get('guilds', []),
):
guild_data['settings'] = utils.find( # type: ignore - This key does not actually exist in the payload
lambda i: i['guild_id'] == guild_data['id'],
@ -1474,7 +1482,7 @@ class ConnectionState:
continue
member = Member(data=item['member'], guild=guild, state=self)
if (presence := item['member'].get('presence')):
if presence := item['member'].get('presence'):
member._presence_update(presence, empty_tuple) # type: ignore
members.append(member)
@ -1496,10 +1504,12 @@ class ConnectionState:
old_member = Member._copy(member)
dispatch = bool(member._update(mdata))
if (presence := mdata.get('presence')):
if presence := mdata.get('presence'):
member._presence_update(presence, empty_tuple) # type: ignore
if should_parse and (old_member._client_status != member._client_status or old_member._activities != member._activities):
if should_parse and (
old_member._client_status != member._client_status or old_member._activities != member._activities
):
self.dispatch('presence_update', old_member, member)
user_update = member._update_inner_user(user)
@ -1512,7 +1522,7 @@ class ConnectionState:
disregard.append(member)
else:
member = Member(data=mdata, guild=guild, state=self)
if (presence := mdata.get('presence')):
if presence := mdata.get('presence'):
member._presence_update(presence, empty_tuple) # type: ignore
to_add.append(member)
@ -1533,10 +1543,12 @@ class ConnectionState:
old_member = Member._copy(member)
dispatch = bool(member._update(mdata))
if (presence := mdata.get('presence')):
if presence := mdata.get('presence'):
member._presence_update(presence, empty_tuple) # type: ignore
if should_parse and (old_member._client_status != member._client_status or old_member._activities != member._activities):
if should_parse and (
old_member._client_status != member._client_status or old_member._activities != member._activities
):
self.dispatch('presence_update', old_member, member)
user_update = member._update_inner_user(user)
@ -1547,7 +1559,7 @@ class ConnectionState:
self.dispatch('member_update', old_member, member)
else:
member = Member(data=mdata, guild=guild, state=self)
if (presence := mdata.get('presence')):
if presence := mdata.get('presence'):
member._presence_update(presence, empty_tuple) # type: ignore
guild._member_list.insert(opdata['index'], member) # Race condition?
@ -1557,7 +1569,11 @@ class ConnectionState:
try:
item = guild._member_list.pop(index)
except IndexError:
_log.debug('GUILD_MEMBER_LIST_UPDATE type DELETE referencing an unknown member index %s in %s. Discarding.', index, guild.id)
_log.debug(
'GUILD_MEMBER_LIST_UPDATE type DELETE referencing an unknown member index %s in %s. Discarding.',
index,
guild.id,
)
continue
if item is not None:
@ -1581,7 +1597,9 @@ class ConnectionState:
def parse_guild_application_command_counts_update(self, data) -> None:
guild = self._get_guild(int(data['guild_id']))
if guild is None:
_log.debug('GUILD_APPLICATION_COMMAND_COUNTS_UPDATE referencing an unknown guild ID: %s. Discarding.', data['guild_id'])
_log.debug(
'GUILD_APPLICATION_COMMAND_COUNTS_UPDATE referencing an unknown guild ID: %s. Discarding.', data['guild_id']
)
return
guild.command_counts = CommandCounts(data.get(0, 0), data.get(1, 0), data.get(2, 0))
@ -1661,17 +1679,19 @@ class ConnectionState:
cache: bool,
force_scraping: bool = False,
channels: List[abcSnowflake] = MISSING,
delay: Union[int, float] = MISSING
delay: Union[int, float] = MISSING,
):
if not guild.me:
await guild.query_members(user_ids=[self.self_id], cache=True) # type: ignore - self_id is always present here
if not force_scraping and any({
guild.me.guild_permissions.administrator,
guild.me.guild_permissions.kick_members,
guild.me.guild_permissions.ban_members,
guild.me.guild_permissions.manage_roles,
}):
if not force_scraping and any(
{
guild.me.guild_permissions.administrator,
guild.me.guild_permissions.kick_members,
guild.me.guild_permissions.ban_members,
guild.me.guild_permissions.manage_roles,
}
):
request = self._chunk_requests.get(guild.id)
if request is None:
self._chunk_requests[guild.id] = request = ChunkRequest(guild.id, self.loop, self._get_guild, cache=cache)
@ -1681,7 +1701,9 @@ class ConnectionState:
request = self._scrape_requests.get(guild.id)
if request is None:
self._scrape_requests[guild.id] = request = MemberSidebar(guild, channels, chunk=False, cache=cache, loop=self.loop, delay=delay)
self._scrape_requests[guild.id] = request = MemberSidebar(
guild, channels, chunk=False, cache=cache, loop=self.loop, delay=delay
)
request.start()
if wait:
@ -1700,7 +1722,9 @@ class ConnectionState:
request = self._scrape_requests.get(guild.id)
if request is None:
self._scrape_requests[guild.id] = request = MemberSidebar(guild, channels, chunk=True, cache=True, loop=self.loop, delay=0)
self._scrape_requests[guild.id] = request = MemberSidebar(
guild, channels, chunk=True, cache=True, loop=self.loop, delay=0
)
request.start()
if wait:

54
discord/tracking.py

@ -69,7 +69,7 @@ class ContextProperties: # Thank you Discord-S.C.U.M
'Verify Email': 'eyJsb2NhdGlvbiI6IlZlcmlmeSBFbWFpbCJ9',
'New Group DM': 'eyJsb2NhdGlvbiI6Ik5ldyBHcm91cCBETSJ9',
'Add Friends to DM': 'eyJsb2NhdGlvbiI6IkFkZCBGcmllbmRzIHRvIERNIn0=',
'None': 'e30='
'None': 'e30=',
}
try:
@ -83,93 +83,67 @@ class ContextProperties: # Thank you Discord-S.C.U.M
@classmethod
def _from_friends_page(cls) -> ContextProperties:
data = {
'location': 'Friends'
}
data = {'location': 'Friends'}
return cls(data)
@classmethod
def _from_context_menu(cls) -> ContextProperties:
data = {
'location': 'ContextMenu'
}
data = {'location': 'ContextMenu'}
return cls(data)
@classmethod
def _from_user_profile(cls) -> ContextProperties:
data = {
'location': 'User Profile'
}
data = {'location': 'User Profile'}
return cls(data)
@classmethod
def _from_add_friend_page(cls) -> ContextProperties:
data = {
'location': 'Add Friend'
}
data = {'location': 'Add Friend'}
return cls(data)
@classmethod
def _from_guild_header_menu(cls) -> ContextProperties:
data = {
'location': 'Guild Header'
}
data = {'location': 'Guild Header'}
return cls(data)
@classmethod
def _from_group_dm(cls) -> ContextProperties:
data = {
'location': 'Group DM'
}
data = {'location': 'Group DM'}
return cls(data)
@classmethod
def _from_new_group_dm(cls) -> ContextProperties:
data = {
'location': 'New Group DM'
}
data = {'location': 'New Group DM'}
return cls(data)
@classmethod
def _from_dm_channel(cls) -> ContextProperties:
data = {
'location': 'DM Channel'
}
data = {'location': 'DM Channel'}
return cls(data)
@classmethod
def _from_add_to_dm(cls) -> ContextProperties:
data = {
'location': 'Add Friends to DM'
}
data = {'location': 'Add Friends to DM'}
return cls(data)
@classmethod
def _from_app(cls) -> ContextProperties:
data = {
'location': '/app'
}
data = {'location': '/app'}
return cls(data)
@classmethod
def _from_login(cls) -> ContextProperties:
data = {
'location': 'Login'
}
data = {'location': 'Login'}
return cls(data)
@classmethod
def _from_register(cls) -> ContextProperties:
data = {
'location': 'Register'
}
data = {'location': 'Register'}
return cls(data)
@classmethod
def _from_verification(cls) -> ContextProperties:
data = {
'location': 'Verify Email'
}
data = {'location': 'Verify Email'}
return cls(data)
@classmethod

2
discord/types/appinfo.py

@ -50,6 +50,7 @@ class _AppInfoOptional(TypedDict, total=False):
hook: bool
max_participants: int
class _PartialAppInfoOptional(TypedDict, total=False):
rpc_origins: List[str]
cover_image: str
@ -63,6 +64,7 @@ class _PartialAppInfoOptional(TypedDict, total=False):
class PartialAppInfo(_PartialAppInfoOptional, BaseAppInfo):
pass
class AppInfo(PartialAppInfo, _AppInfoOptional):
owner: User
integration_public: bool

2
discord/types/guild.py

@ -179,4 +179,4 @@ class RolePositionUpdate(_RolePositionRequired, total=False):
class SupplementalGuild(UnavailableGuild):
embedded_activities: list
voice_states: List[GuildVoiceState]
voice_states: List[GuildVoiceState]

22
discord/user.py

@ -29,7 +29,16 @@ from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING, Union
import discord.abc
from .asset import Asset
from .colour import Colour
from .enums import Locale, AppCommandType, DefaultAvatar, HypeSquadHouse, PremiumType, RelationshipAction, RelationshipType, try_enum
from .enums import (
Locale,
AppCommandType,
DefaultAvatar,
HypeSquadHouse,
PremiumType,
RelationshipAction,
RelationshipType,
try_enum,
)
from .errors import ClientException, NotFound
from .flags import PublicUserFlags
from .iterators import FakeCommandIterator
@ -67,6 +76,7 @@ __all__ = (
class Note:
"""Represents a Discord note."""
__slots__ = ('_state', '_note', '_user_id', '_user')
def __init__(
@ -171,7 +181,7 @@ class Note:
return base + '>'
def __len__(self) -> int:
if (note := self._note):
if note := self._note:
return len(note)
return 0
@ -973,7 +983,9 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
HTTPException
Blocking the user failed.
"""
await self._state.http.add_relationship(self.id, type=RelationshipType.blocked.value, action=RelationshipAction.block)
await self._state.http.add_relationship(
self.id, type=RelationshipType.blocked.value, action=RelationshipAction.block
)
async def unblock(self) -> None:
"""|coro|
@ -1017,9 +1029,7 @@ class User(BaseUser, discord.abc.Connectable, discord.abc.Messageable):
"""
await self._state.http.send_friend_request(self.name, self.discriminator)
async def profile(
self, *, with_mutuals: bool = True, fetch_note: bool = True
) -> UserProfile:
async def profile(self, *, with_mutuals: bool = True, fetch_note: bool = True) -> UserProfile:
"""|coro|
Gets the user's profile.

39
discord/utils.py

@ -1262,6 +1262,7 @@ class Browser: # Inspired from https://github.com/NoahCardoza/CaptchaHarvester
def get_mac_browser(pkg: str, binary: str) -> Optional[os.PathLike]:
import plistlib as plist
pfile: str = f'{os.environ["HOME"]}/Library/Preferences/{pkg}.plist'
if os.path.exists(pfile):
with open(pfile, 'rb') as f:
@ -1271,6 +1272,7 @@ class Browser: # Inspired from https://github.com/NoahCardoza/CaptchaHarvester
def get_windows_browser(browser: str) -> Optional[str]:
import winreg as reg
reg_path: str = f'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\{browser}.exe'
exe_path: Optional[str] = None
for install_type in reg.HKEY_CURRENT_USER, reg.HKEY_LOCAL_MACHINE:
@ -1288,6 +1290,7 @@ class Browser: # Inspired from https://github.com/NoahCardoza/CaptchaHarvester
def get_linux_browser(browser: str) -> Optional[str]:
from shutil import which as exists
possibilities: List[str] = [browser + channel for channel in ('', '-beta', '-dev', '-developer', '-canary')]
for browser in possibilities:
if exists(browser):
@ -1311,7 +1314,7 @@ class Browser: # Inspired from https://github.com/NoahCardoza/CaptchaHarvester
'chromium': functools.partial(get_linux_browser, 'chromium'),
'microsoft-edge': functools.partial(get_linux_browser, 'microsoft-edge'),
'opera': functools.partial(get_linux_browser, 'opera'),
}
},
}
def get_browser(self, browser: Optional[BrowserEnum] = None) -> Optional[str]:
@ -1337,27 +1340,29 @@ class Browser: # Inspired from https://github.com/NoahCardoza/CaptchaHarvester
width: int = 400,
height: int = 500,
browser_args: List[str] = [],
extensions: Optional[str] = None
extensions: Optional[str] = None,
) -> None:
browser_command: List[str] = [self.browser, *browser_args]
if extensions:
browser_command.append(f'--load-extension={extensions}')
browser_command.extend((
'--disable-default-apps',
'--no-default-browser-check',
'--no-check-default-browser',
'--no-first-run',
'--ignore-certificate-errors',
'--disable-background-networking',
'--disable-component-update',
'--disable-domain-reliability',
f'--user-data-dir={os.path.join(tempfile.TemporaryDirectory().name, "Profiles")}',
f'--host-rules=MAP {domain} {server[0]}:{server[1]}',
f'--window-size={width},{height}',
f'--app=https://{domain}'
))
browser_command.extend(
(
'--disable-default-apps',
'--no-default-browser-check',
'--no-check-default-browser',
'--no-first-run',
'--ignore-certificate-errors',
'--disable-background-networking',
'--disable-component-update',
'--disable-domain-reliability',
f'--user-data-dir={os.path.join(tempfile.TemporaryDirectory().name, "Profiles")}',
f'--host-rules=MAP {domain} {server[0]}:{server[1]}',
f'--window-size={width},{height}',
f'--app=https://{domain}',
)
)
self.proc = subprocess.Popen(browser_command, stdout=-1, stderr=-1)
@ -1392,7 +1397,7 @@ async def _get_build_number(session: ClientSession) -> int: # Thank you Discord
build_request = await session.get(build_url, timeout=7)
build_file = await build_request.text()
build_index = build_file.find('buildNumber') + 24
return int(build_file[build_index:build_index + 6])
return int(build_file[build_index : build_index + 6])
except asyncio.TimeoutError:
_log.critical('Could not fetch client build number. Falling back to hardcoded value...')
return 117300

22
discord/voice_client.py

@ -259,9 +259,7 @@ class Player:
"""Indicates if we're playing audio, but if we're paused."""
return self._player and self._player.is_paused()
def play(
self, source: AudioSource, *, after: Callable[[Optional[Exception]], Any] = None
) -> None:
def play(self, source: AudioSource, *, after: Callable[[Optional[Exception]], Any] = None) -> None:
"""Plays an :class:`AudioSource`.
The finalizer, ``after`` is called after the source has been exhausted
@ -508,7 +506,11 @@ class VoiceClient(VoiceProtocol):
await self._state.client.change_voice_state(channel=channel)
async def voice_disconnect(self) -> None:
_log.info('The voice handshake is being terminated for channel ID %s (guild ID %s).', (await self.channel._get_channel()).id, getattr(self.guild, 'id', None))
_log.info(
'The voice handshake is being terminated for channel ID %s (guild ID %s).',
(await self.channel._get_channel()).id,
getattr(self.guild, 'id', None),
)
if self.guild:
await self.guild.change_voice_state(channel=None)
else:
@ -738,7 +740,7 @@ class VoiceClient(VoiceProtocol):
@staticmethod
def _strip_header(data) -> bytes:
if data[0] == 0xbe and data[1] == 0xde and len(data) > 4:
if data[0] == 0xBE and data[1] == 0xDE and len(data) > 4:
_, length = struct.unpack_from('>HH', data)
offset = 4 + length * 4
data = data[offset:]
@ -801,7 +803,7 @@ class VoiceClient(VoiceProtocol):
return self._strip_header(box.decrypt(bytes(data), bytes(nonce)))
def play(self, source: AudioSource, *, after: Callable[[Optional[Exception]], Any]=None) -> None:
def play(self, source: AudioSource, *, after: Callable[[Optional[Exception]], Any] = None) -> None:
"""Plays an :class:`AudioSource`.
The finalizer, ``after`` is called after the source has been exhausted
@ -857,10 +859,10 @@ class VoiceClient(VoiceProtocol):
@sink.setter
def sink(self, value):
self.listener.sink = value
#if not isinstance(value, AudioSink):
#raise TypeError('Expected AudioSink not {value.__class__.__name__}')
#if self._recorder is None:
#raise ValueError('Not listening')
# if not isinstance(value, AudioSink):
# raise TypeError('Expected AudioSink not {value.__class__.__name__}')
# if self._recorder is None:
# raise ValueError('Not listening')
def send_audio_packet(self, data: bytes) -> None:
"""Sends an audio packet composed of the data.

4
discord/welcome_screen.py

@ -61,9 +61,7 @@ class WelcomeChannel:
The emoji shown under the description.
"""
def __init__(
self, *, channel: Snowflake, description: str, emoji: Optional[Union[PartialEmoji, Emoji]] = None
) -> None:
def __init__(self, *, channel: Snowflake, description: str, emoji: Optional[Union[PartialEmoji, Emoji]] = None) -> None:
self.channel = channel
self.description = description
self.emoji = emoji

Loading…
Cancel
Save