Skip to content

Commit b4ed080

Browse files
mAxYoLo01EepyElvyraDamegopre-commit-ci[bot]FayeDel
authored
chore: Update docs (#1013)
* Update base.py * refactor: change condition for getting error message (#973) * refactor: change condition for getting error message * ci: correct from checks. Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * revert!: revert removed fixes for attrs (#974) * return back fix * return back Delta fix * make check like Delta * Update attrs_utils.py * Update client.py (#975) * refactor: move ``Emoji`` to own module (#978) * refactor: separate Emoji to own module * fix imports * rename imports in http * change brackets * ci: pre-commit * fix: fix incorrect role converts in Emoji * ref: remove Role import * fix: added default None value to optional args (#982) * fix: fix error ``Attachment`` is not JSON serializable (#983) * fix: fix error ``Attachment`` is not JSON serializable * Update interactions/api/models/message.py Co-authored-by: EdVraz <[email protected]> * chore: Version bump (#984) * feat!: Add converters to components (#981) * refactor!: Add converters to components * ci: run pre-commit * doc: add missed docstring * oop * fix: fix option type parsing in option decorator (#986) * fix: fix error with converting components in edit (#987) * fix: fix error with converting components in edit * add build components to message.edit * doc * Revert "doc" This reverts commit a9eda7b. * feat: Add support for message_delete_bulk event (#990) * feat: add support for messa_delete_bulk event * fix: add missing comma * ci: weekly check. (#991) updates: - [github.com/PyCQA/flake8: 4.0.1 → 5.0.2](PyCQA/flake8@4.0.1...5.0.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * feat: add ``__str__`` to ``Emoji`` (#988) * fix: remove bug with converting empty list to actionrow (#997) * fix: fix converting empty list to actionrow * move check * ci: correct from checks. Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * fix: wrong sequence in getting channel overwrites (#998) * fix: fix few bugs with reactions (#993) * chore: bump version to 4.3.1 * fix: add search_iterable() to __all__ (#1003) * fix: Remove empty _client attribute in _json property (#999) * fix: Remove empty _client attribute in _json property * refactor: conditional logic * fix: add member's _client for message reactions (#994) * fix: add member's _client for message reactions * refactor: change to add_client Yes I did not know that it exists sorry * ci: weekly check. (#1009) updates: - [github.com/PyCQA/flake8: 5.0.2 → 5.0.4](PyCQA/flake8@5.0.2...5.0.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * refactor: change condition in update dispatch (#1004) * docs: fix incorrect codeblocks (#1006) * docs: fix incorrect codeblocks * Update interactions/client/models/component.py Co-authored-by: EdVraz <[email protected]> Co-authored-by: EdVraz <[email protected]> * feat: Add member and channel permissions calculation functions (#969) * feat: added member and channel permissions functions * ci: correct from checks. * docs: update docs * refactor: switch from ALL_PERMISSIONS to Permissions.ALL & DEFAULT * feat: add default permissions if in DM * fix: small fixes Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: EdVraz <[email protected]> Co-authored-by: Damego <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: DeltaX <[email protected]> Co-authored-by: Damego <[email protected]>
1 parent bf9771a commit b4ed080

File tree

24 files changed

+369
-163
lines changed

24 files changed

+369
-163
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ repos:
3737
types: [file, python]
3838
args: [--line-length=100]
3939
- repo: https://github.com/PyCQA/flake8
40-
rev: 4.0.1
40+
rev: 5.0.4
4141
hooks:
4242
- id: flake8
4343
name: flake8 Formatting

interactions/api/gateway/client.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -372,13 +372,9 @@ def _dispatch_event(self, event: str, data: dict) -> None:
372372
elif data["type"] == InteractionType.MODAL_SUBMIT:
373373
_name = f"modal_{_context.data.custom_id}"
374374

375-
if _context.data._json.get("components"):
375+
if _context.data.components:
376376
for component in _context.data.components:
377-
if component.get("components"):
378-
__args.append(
379-
[_value["value"] for _value in component["components"]][0]
380-
)
381-
else:
377+
if component.components:
382378
__args.append([_value.value for _value in component.components][0])
383379

384380
self._dispatch.dispatch("on_modal", _context)
@@ -417,6 +413,7 @@ def _dispatch_event(self, event: str, data: dict) -> None:
417413
"ChannelPins",
418414
"MessageReaction",
419415
"MessageReactionRemove",
416+
"MessageDelete",
420417
# Extend this for everything that should not be cached
421418
]:
422419
id = None
@@ -466,7 +463,10 @@ def __modify_guild_cache():
466463
self._dispatch.dispatch(f"on_{name}", obj)
467464
__modify_guild_cache()
468465

469-
elif "_update" in name and hasattr(obj, "id"):
466+
elif "_update" in name:
467+
self._dispatch.dispatch(f"on_raw_{name}", obj)
468+
if not id:
469+
return
470470
old_obj = self._http.cache[model].get(id)
471471
if old_obj:
472472
before = model(**old_obj._json)
@@ -481,14 +481,15 @@ def __modify_guild_cache():
481481
self._dispatch.dispatch(
482482
f"on_{name}", before, old_obj
483483
) # give previously stored and new one
484-
return
485484

486485
elif "_remove" in name or "_delete" in name:
487486
self._dispatch.dispatch(f"on_raw_{name}", obj)
488487
__modify_guild_cache()
489488
if id:
490489
old_obj = _cache.pop(id)
491490
self._dispatch.dispatch(f"on_{name}", old_obj)
491+
elif "_delete_bulk" in name:
492+
self._dispatch.dispatch(f"on_{name}", obj)
492493

493494
else:
494495
self._dispatch.dispatch(f"on_{name}", obj)

interactions/api/http/emoji.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from typing import List, Optional
22

33
from ...api.cache import Cache
4-
from ...api.models.guild import Emoji, Guild
5-
from ...api.models.misc import Snowflake
4+
from ..models.emoji import Emoji
5+
from ..models.guild import Guild
6+
from ..models.misc import Snowflake
67
from .request import _Request
78
from .route import Route
89

interactions/api/http/invite.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from .request import _Request
55
from .route import Route
66

7-
__all__ = ["InviteRequest"]
7+
__all__ = ("InviteRequest",)
88

99

1010
class InviteRequest:

interactions/api/http/member.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from typing import List, Optional
22

33
from ...api.cache import Cache
4-
from ...api.models.guild import Guild
5-
from ...api.models.member import Member
6-
from ...api.models.misc import Snowflake
4+
from ..models.guild import Guild
5+
from ..models.member import Member
6+
from ..models.misc import Snowflake
77
from .request import _Request
88
from .route import Route
99

interactions/api/http/request.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ async def request(self, route: Route, **kwargs) -> Optional[Any]:
163163
self.buckets[route.endpoint] = _bucket
164164
# real-time replacement/update/add if needed.
165165
if isinstance(data, dict) and (
166-
data.get("errors") or (data.get("code") and data.get("code") != 429)
166+
data.get("errors")
167+
or ((code := data.get("code")) and code != 429 and data.get("message"))
167168
):
168169
log.debug(
169170
f"RETURN {response.status}: {dumps(data, indent=4, sort_keys=True)}"

interactions/api/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .attrs_utils import * # noqa: F401 F403
99
from .audit_log import * # noqa: F401 F403
1010
from .channel import * # noqa: F401 F403
11+
from .emoji import * # noqa: F401 F403
1112
from .flags import * # noqa: F401 F403
1213
from .guild import * # noqa: F401 F403
1314
from .gw import * # noqa: F401 F403

interactions/api/models/attrs_utils.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,30 @@ def __init__(self, kwargs_dict: dict = None, /, **other_kwargs):
4747
discord_name = attrib_name
4848

4949
if (value := kwargs.pop(discord_name, MISSING)) is not MISSING:
50-
if value is not None and attrib.metadata.get("add_client"):
50+
if (
51+
value is not None
52+
and attrib.metadata.get("add_client")
53+
and client is not None
54+
):
5155
if isinstance(value, list):
5256
for item in value:
53-
item["_client"] = client
57+
if isinstance(item, dict):
58+
item["_client"] = client
59+
elif isinstance(item, DictSerializerMixin):
60+
item._client = client
5461
else:
55-
value["_client"] = client
62+
if isinstance(value, dict):
63+
value["_client"] = client
64+
elif isinstance(value, DictSerializerMixin):
65+
value._client = client
66+
67+
# make sure json is recursively handled
68+
if isinstance(value, list):
69+
self._json[attrib_name] = [
70+
i._json if isinstance(i, DictSerializerMixin) else i for i in value
71+
]
72+
elif isinstance(value, DictSerializerMixin):
73+
self._json[attrib_name] = value._json # type: ignore
5674

5775
passed_kwargs[attrib_name] = value
5876

interactions/api/models/channel.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
define,
1212
field,
1313
)
14+
from .flags import Permissions
1415
from .misc import File, IDMixin, Overwrite, Snowflake
1516
from .user import User
1617
from .webhook import Webhook
@@ -363,11 +364,11 @@ async def modify(
363364
)
364365
_nsfw = self.nsfw if nsfw is MISSING else nsfw
365366
_permission_overwrites = (
366-
[overwrite._json for overwrite in self.permission_overwrites]
367+
[overwrite._json for overwrite in permission_overwrites]
368+
if permission_overwrites is not MISSING
369+
else [overwrite._json for overwrite in self.permission_overwrites]
367370
if self.permission_overwrites
368371
else None
369-
if permission_overwrites is MISSING
370-
else [overwrite._json for overwrite in permission_overwrites]
371372
)
372373
_type = self.type
373374

@@ -1207,6 +1208,67 @@ async def join(self) -> None:
12071208

12081209
await self._client.join_thread(int(self.id))
12091210

1211+
async def get_permissions_for(self, member: "Member") -> Permissions:
1212+
"""
1213+
Returns the permissions of the member in this specific channel.
1214+
1215+
.. note::
1216+
The permissions returned by this function take into account role and
1217+
user overwrites that can be assigned to channels or categories. If you
1218+
don't need these overwrites, look into :meth:`.Member.get_guild_permissions`.
1219+
1220+
:param member: The member to get the permissions from
1221+
:type member: Member
1222+
:return: Permissions of the member in this channel
1223+
:rtype: Permissions
1224+
"""
1225+
if not self.guild_id:
1226+
return Permissions.DEFAULT
1227+
1228+
from .guild import Guild
1229+
1230+
guild = Guild(**await self._client.get_guild(int(self.guild_id)), _client=self._client)
1231+
1232+
permissions = await member.get_guild_permissions(guild)
1233+
1234+
if permissions & Permissions.ADMINISTRATOR == Permissions.ADMINISTRATOR:
1235+
return Permissions.ALL
1236+
1237+
# @everyone role overwrites
1238+
from ...client.models.utils import search_iterable
1239+
1240+
overwrite_everyone = search_iterable(
1241+
self.permission_overwrites, lambda overwrite: int(overwrite.id) == int(self.guild_id)
1242+
)
1243+
if overwrite_everyone:
1244+
permissions &= ~int(overwrite_everyone[0].deny)
1245+
permissions |= int(overwrite_everyone[0].allow)
1246+
1247+
# Apply role specific overwrites
1248+
allow, deny = 0, 0
1249+
for role_id in member.roles:
1250+
overwrite_role = search_iterable(
1251+
self.permission_overwrites, lambda overwrite: int(overwrite.id) == int(role_id)
1252+
)
1253+
if overwrite_role:
1254+
allow |= int(overwrite_role[0].allow)
1255+
deny |= int(overwrite_role[0].deny)
1256+
1257+
if deny:
1258+
permissions &= ~deny
1259+
if allow:
1260+
permissions |= allow
1261+
1262+
# Apply member specific overwrites
1263+
overwrite_member = search_iterable(
1264+
self.permission_overwrites, lambda overwrite: int(overwrite.id) == int(member.id)
1265+
)
1266+
if overwrite_member:
1267+
permissions &= ~int(overwrite_member[0].deny)
1268+
permissions |= int(overwrite_member[0].allow)
1269+
1270+
return Permissions(permissions)
1271+
12101272

12111273
@define()
12121274
class Thread(Channel):

interactions/api/models/emoji.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
from typing import TYPE_CHECKING, List, Optional, Union
2+
3+
from ..error import LibraryException
4+
from .attrs_utils import ClientSerializerMixin, convert_list, define, field
5+
from .misc import Snowflake
6+
from .user import User
7+
8+
if TYPE_CHECKING:
9+
from ..http import HTTPClient
10+
from .guild import Guild
11+
12+
__all__ = ("Emoji",)
13+
14+
15+
@define()
16+
class Emoji(ClientSerializerMixin):
17+
"""
18+
A class objecting representing an emoji.
19+
20+
:ivar Optional[Snowflake] id?: Emoji id
21+
:ivar Optional[str] name?: Emoji name.
22+
:ivar Optional[List[int]] roles?: Roles allowed to use this emoji
23+
:ivar Optional[User] user?: User that created this emoji
24+
:ivar Optional[bool] require_colons?: Status denoting of this emoji must be wrapped in colons
25+
:ivar Optional[bool] managed?: Status denoting if this emoji is managed (by an integration)
26+
:ivar Optional[bool] animated?: Status denoting if this emoji is animated
27+
:ivar Optional[bool] available?: Status denoting if this emoji can be used. (Can be false via server boosting)
28+
"""
29+
30+
id: Optional[Snowflake] = field(converter=Snowflake, default=None)
31+
name: Optional[str] = field(default=None)
32+
roles: Optional[List[int]] = field(converter=convert_list(int), default=None)
33+
user: Optional[User] = field(converter=User, default=None)
34+
require_colons: Optional[bool] = field(default=None)
35+
managed: Optional[bool] = field(default=None)
36+
animated: Optional[bool] = field(default=None)
37+
available: Optional[bool] = field(default=None)
38+
39+
def __str__(self):
40+
return (
41+
f"<{'a' if self.animated else ''}:{self.name}:{self.id}>"
42+
if self.id is not None
43+
else self.name
44+
)
45+
46+
@classmethod
47+
async def get(
48+
cls,
49+
guild_id: Union[int, Snowflake, "Guild"],
50+
emoji_id: Union[int, Snowflake],
51+
client: "HTTPClient",
52+
) -> "Emoji":
53+
"""
54+
Gets an emoji.
55+
56+
:param guild_id: The id of the guild of the emoji
57+
:type guild_id: Union[int, Snowflake, "Guild"]
58+
:param emoji_id: The id of the emoji
59+
:type emoji_id: Union[int, Snowflake]
60+
:param client: The HTTPClient of your bot. Equals to ``bot._http``
61+
:type client: HTTPClient
62+
:return: The Emoji as object
63+
:rtype: Emoji
64+
"""
65+
66+
_guild_id = int(guild_id) if isinstance(guild_id, (int, Snowflake)) else int(guild_id.id)
67+
68+
res = await client.get_guild_emoji(guild_id=_guild_id, emoji_id=int(emoji_id))
69+
return cls(**res, _client=client)
70+
71+
@classmethod
72+
async def get_all_of_guild(
73+
cls,
74+
guild_id: Union[int, Snowflake, "Guild"],
75+
client: "HTTPClient",
76+
) -> List["Emoji"]:
77+
"""
78+
Gets all emoji of a guild.
79+
80+
:param guild_id: The id of the guild to get the emojis of
81+
:type guild_id: Union[int, Snowflake, "Guild"]
82+
:param client: The HTTPClient of your bot. Equals to ``bot._http``
83+
:type client: HTTPClient
84+
:return: The Emoji as list
85+
:rtype: List[Emoji]
86+
"""
87+
88+
_guild_id = int(guild_id) if isinstance(guild_id, (int, Snowflake)) else int(guild_id.id)
89+
90+
res = await client.get_all_emoji(guild_id=_guild_id)
91+
return [cls(**emoji, _client=client) for emoji in res]
92+
93+
async def delete(
94+
self,
95+
guild_id: Union[int, Snowflake, "Guild"],
96+
reason: Optional[str] = None,
97+
) -> None:
98+
"""
99+
Deletes the emoji.
100+
101+
:param guild_id: The guild id to delete the emoji from
102+
:type guild_id: Union[int, Snowflake, "Guild"]
103+
:param reason?: The reason of the deletion
104+
:type reason?: Optional[str]
105+
"""
106+
if not self._client:
107+
raise LibraryException(code=13)
108+
109+
_guild_id = int(guild_id) if isinstance(guild_id, (int, Snowflake)) else int(guild_id.id)
110+
111+
return await self._client.delete_guild_emoji(
112+
guild_id=_guild_id, emoji_id=int(self.id), reason=reason
113+
)
114+
115+
@property
116+
def url(self) -> str:
117+
"""
118+
Returns the emoji's URL.
119+
120+
:return: URL of the emoji
121+
:rtype: str
122+
"""
123+
url = f"https://cdn.discordapp.com/emojis/{self.id}"
124+
url += ".gif" if self.animated else ".png"
125+
return url

0 commit comments

Comments
 (0)