Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions interactions/api/gateway/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ async def wait_until_ready(self) -> None:
"""Waits for the client to become ready according to the Gateway."""
await self.ready.wait()

def _dispatch_event(self, event: str, data: dict) -> None: # sourcery no-metrics
def _dispatch_event(self, event: str, data: dict) -> None:
"""
Dispatches an event from the Gateway.

Expand All @@ -273,11 +273,12 @@ def _dispatch_event(self, event: str, data: dict) -> None: # sourcery no-metric
:param data: The data for the event.
:type data: dict
"""
# sourcery no-metrics
path: str = "interactions"
path += ".models" if event == "INTERACTION_CREATE" else ".api.models"
if event == "INTERACTION_CREATE":
if data.get("type"):
# sourcery skip: extract-method
# sourcery skip: dict-assign-update-to-union, extract-method, low-code-quality
_context = self.__contextualize(data)
_name: str = ""
__args: list = [_context]
Expand Down
5 changes: 2 additions & 3 deletions interactions/api/gateway/heartbeat.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
from asyncio import AbstractEventLoop, Event
from sys import version_info

Expand All @@ -15,8 +16,6 @@ def __init__(self, loop: AbstractEventLoop) -> None:
:param loop: The event loop to base the asynchronous manager.
:type loop: AbstractEventLoop
"""
try:
with contextlib.suppress(TypeError):
self.event = Event(loop=loop) if version_info < (3, 10) else Event()
except TypeError:
pass
self.delay = 0.0
5 changes: 3 additions & 2 deletions interactions/api/http/invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ async def get_invite(
"""
params_set = {
"with_counts=true" if with_counts else None,
"with_expiration=false" if not with_expiration else None,
None if with_expiration else "with_expiration=false",
f"guild_scheduled_event_id={guild_scheduled_event_id}"
if guild_scheduled_event_id
else None,
}

final = "&".join([item for item in params_set if item is not None])

return await self._req.request(
Route("GET", f"/invites/{invite_code}{'?' + final if final is not None else ''}")
Route("GET", f"/invites/{invite_code}{f'?{final}' if final is not None else ''}")
)

async def delete_invite(self, invite_code: str, reason: Optional[str] = None) -> dict:
Expand Down
2 changes: 1 addition & 1 deletion interactions/api/http/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ async def edit_message(
file._fp,
)
part.set_content_disposition(
"form-data", name="files[" + str(id) + "]", filename=file._filename
"form-data", name=f"files[{str(id)}]", filename=file._filename
)

return await self._req.request(
Expand Down
6 changes: 4 additions & 2 deletions interactions/api/http/reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ async def get_reactions_of_emoji(
return await self._req.request(
Route(
"GET",
"/channels/{channel_id}/messages/{message_id}/reactions/{emoji}"
+ f"{'?' + final if final is not None else ''}",
(
"/channels/{channel_id}/messages/{message_id}/reactions/{emoji}"
+ f"{f'?{final}' if final is not None else ''}"
),
channel_id=channel_id,
message_id=message_id,
emoji=emoji,
Expand Down
20 changes: 10 additions & 10 deletions interactions/api/http/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]:
:return: The contents of the request if any.
:rtype: Optional[Any]
"""
# sourcery skip: low-code-quality

kwargs["headers"] = {**self._headers, **kwargs.get("headers", {})}

if kwargs.get("json"):
kwargs["headers"]["Content-Type"] = "application/json"

reason = kwargs.pop("reason", None)
if reason:
if reason := kwargs.pop("reason", None):
kwargs["headers"]["X-Audit-Log-Reason"] = quote(reason, safe="/ ")

# Huge credit and thanks to LordOfPolls for the lock/retry logic.
Expand Down Expand Up @@ -185,21 +185,21 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]:
severity=50,
)
if response.status == 429:
if not is_global:
log.warning(
f"The HTTP client has encountered a per-route ratelimit. Locking down future requests for {reset_after} seconds."
)
_limiter.reset_after = reset_after
await asyncio.sleep(_limiter.reset_after)
continue
else:
if is_global:
log.warning(
f"The HTTP client has encountered a global ratelimit. Locking down future requests for {reset_after} seconds."
)
self._global_lock.reset_after = reset_after
self._loop.call_later(
self._global_lock.reset_after, self._global_lock.lock.release
)
else:
log.warning(
f"The HTTP client has encountered a per-route ratelimit. Locking down future requests for {reset_after} seconds."
)
_limiter.reset_after = reset_after
await asyncio.sleep(_limiter.reset_after)
continue
if remaining is not None and int(remaining) == 0:
log.warning(
f"The HTTP client has exhausted a per-route ratelimit. Locking route for {reset_after} seconds."
Expand Down
3 changes: 1 addition & 2 deletions interactions/api/http/scheduledEvent.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ async def create_scheduled_event(self, guild_id: Snowflake, payload: dict) -> di
data = {k: v for k, v in payload.items() if k in valid_keys}

return await self._req.request(
Route("POST", "/guilds/{guild_id}/scheduled-events", guild_id=int(guild_id)),
json=data,
Route("POST", "/guilds/{guild_id}/scheduled-events", guild_id=guild_id), json=data
)

async def get_scheduled_event(
Expand Down
1 change: 1 addition & 0 deletions interactions/api/models/attrs_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class DictSerializerMixin:
"""Should the kwargs be deepcopied or not?"""

def __init__(self, kwargs_dict: dict = None, /, **other_kwargs):
# sourcery skip: low-code-quality
kwargs = kwargs_dict or other_kwargs
client = kwargs.pop("_client", None)

Expand Down
4 changes: 2 additions & 2 deletions interactions/api/models/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ async def send(
List["SelectMenu"],
]
] = MISSING,
) -> "Message":
) -> "Message": # noqa # sourcery skip: dict-assign-update-to-union
"""
Sends a message in the channel.
Expand Down Expand Up @@ -757,7 +757,7 @@ async def purge(
before: Optional[int] = MISSING,
reason: Optional[str] = None,
bulk: Optional[bool] = True,
) -> List["Message"]:
) -> List["Message"]: # noqa # sourcery skip: low-code-quality
"""
Purges a given amount of messages from a channel. You can specify a check function to exclude specific messages.
Expand Down
6 changes: 3 additions & 3 deletions interactions/api/models/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ async def modify_channel(
auto_archive_duration: Optional[int] = MISSING,
locked: Optional[bool] = MISSING,
reason: Optional[str] = None,
) -> Channel:
) -> Channel: # sourcery skip: low-code-quality
"""
Edits a channel of the guild.

Expand Down Expand Up @@ -1124,7 +1124,7 @@ async def modify(
description: Optional[str] = MISSING,
premium_progress_bar_enabled: Optional[bool] = MISSING,
reason: Optional[str] = None,
) -> "Guild":
) -> "Guild": # sourcery skip: low-code-quality
"""
Modifies the current guild.

Expand Down Expand Up @@ -2181,7 +2181,7 @@ async def modify_auto_moderation_rule(
exempt_roles: Optional[List[int]] = MISSING,
exempt_channels: Optional[List[int]] = MISSING,
reason: Optional[str] = None,
) -> "AutoModerationRule":
) -> "AutoModerationRule": # noqa # sourcery skip: compare-via-equals
"""
Edits an AutoMod rule

Expand Down
7 changes: 3 additions & 4 deletions interactions/api/models/message.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
from datetime import datetime
from enum import IntEnum
from typing import TYPE_CHECKING, List, Optional, Union
Expand Down Expand Up @@ -626,10 +627,8 @@ def remove_author(self) -> None:
Removes the embed's author
"""

try:
with contextlib.suppress(AttributeError):
del self.author
except AttributeError:
pass

def set_author(
self,
Expand Down Expand Up @@ -1055,7 +1054,7 @@ async def reply(
List["SelectMenu"],
]
] = MISSING,
) -> "Message":
) -> "Message": # sourcery skip: dict-assign-update-to-union
"""
Sends a new message replying to the old.

Expand Down
2 changes: 1 addition & 1 deletion interactions/api/models/webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ async def modify(
name: Optional[str] = MISSING,
channel_id: int = MISSING,
avatar: Optional[Image] = MISSING,
) -> "Webhook":
) -> "Webhook": # sourcery skip: compare-via-equals
"""
Modifies the current webhook.

Expand Down
30 changes: 15 additions & 15 deletions interactions/client/bot.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
import re
import sys
from asyncio import AbstractEventLoop, CancelledError, get_event_loop, iscoroutinefunction
Expand Down Expand Up @@ -187,7 +188,7 @@ async def __compare_sync(
_command: dict = {}

def __check_options(command, data):
# sourcery skip: none-compare
# sourcery skip: low-code-quality, none-compare
# sourcery no-metrics
_command_option_names = [option["name"] for option in command.get("options")]
_data_option_names = [option["name"] for option in data.get("options")]
Expand Down Expand Up @@ -266,11 +267,14 @@ def __check_options(command, data):
else:
continue

for i, __name in enumerate(_command_option_names):
if _data_option_names[i] != __name:
return False, command

return True, command
return next(
(
(False, command)
for i, __name in enumerate(_command_option_names)
if _data_option_names[i] != __name
),
(True, command),
)

for command in pool:
if command["name"] == data["name"]:
Expand Down Expand Up @@ -449,6 +453,7 @@ async def __sync(self) -> None: # sourcery no-metrics
.. warning::
This is an internal method. Do not call it unless you know what you are doing!
"""
# sourcery skip: low-code-quality

log.debug("starting command sync")
_guilds = await self._http.get_self_guilds()
Expand Down Expand Up @@ -479,7 +484,7 @@ async def __sync(self) -> None: # sourcery no-metrics
)
except LibraryException as e:
if int(e.code) != 50001:
raise LibraryException(code=e.code, message=e.message)
raise LibraryException(code=e.code, message=e.message) from e

log.warning(
f"Your bot is missing access to guild with corresponding id {_id}! "
Expand Down Expand Up @@ -1345,23 +1350,17 @@ def remove(

if ext_name != "Extension":
_extension = self._extensions.get(ext_name)
try:
with contextlib.suppress(AttributeError):
self._loop.create_task(
_extension.teardown(remove_commands=remove_commands)
) # made for Extension, usable by others
except AttributeError:
pass

del sys.modules[_name]

else:
try:
with contextlib.suppress(AttributeError):
self._loop.create_task(
extension.teardown(remove_commands=remove_commands)
) # made for Extension, usable by others
except AttributeError:
pass

del self._extensions[_name]

log.debug(f"Removed extension {name}.")
Expand Down Expand Up @@ -1539,6 +1538,7 @@ def setup(client):
client: Client

def __new__(cls, client: Client, *args, **kwargs) -> "Extension":
# sourcery skip: low-code-quality

self = super().__new__(cls)

Expand Down
12 changes: 7 additions & 5 deletions interactions/client/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,11 +336,13 @@ def __attrs_post_init__(self) -> None:
target = self.data.target_id

if self.data.type == 2:
if self.guild_id and str(self.data.target_id) in self.data.resolved.members:
# member id would have potential to exist, and therefore have target def priority.
self.target = self.data.resolved.members[target]
else:
self.target = self.data.resolved.users[target]
self.target = (
self.data.resolved.members[target]
if self.guild_id and str(self.data.target_id) in self.data.resolved.members
else self.data.resolved.users[target]
)
# member id would have potential to exist, and therefore have target def priority.

elif self.data.type == 3:
self.target = self.data.resolved.messages[target]

Expand Down
2 changes: 1 addition & 1 deletion interactions/client/decor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def command(
description_localizations: Optional[Dict[Union[str, Locale], str]] = MISSING,
default_member_permissions: Optional[Union[int, Permissions]] = MISSING,
dm_permission: Optional[bool] = MISSING
) -> Union[List[dict], dict]:
) -> Union[List[dict], dict]: # sourcery skip: low-code-quality
"""
A wrapper designed to interpret the client-facing API for
how a command is to be created and used.
Expand Down
5 changes: 2 additions & 3 deletions interactions/client/models/component.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import contextlib
from typing import List, Optional

from ...api.error import LibraryException
Expand Down Expand Up @@ -30,10 +31,8 @@ def __setattr__(self, key, value) -> None:
key not in self._json or value != self._json.get(key)
):
if value is not None and value is not MISSING:
try:
with contextlib.suppress(AttributeError):
value = [val._json for val in value] if isinstance(value, list) else value._json
except AttributeError:
pass
self._json.update({key: value})
elif value is None and key in self._json.keys():
del self._json[key]
Expand Down