diff --git a/.gitignore b/.gitignore index b647843..1219110 100644 --- a/.gitignore +++ b/.gitignore @@ -141,3 +141,4 @@ cython_debug/ # Editors .vscode/ .idea/ +.nova/ diff --git a/nextcord/exceptions.py b/nextcord/exceptions.py index 3b0e43b..014134e 100644 --- a/nextcord/exceptions.py +++ b/nextcord/exceptions.py @@ -1,3 +1,22 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + + class NextcordException(Exception): ... @@ -25,3 +44,7 @@ def __init__(self) -> None: "You have been banned by Cloudflare. " "See https://discord.dev/topics/rate-limits#invalid-request-limit-aka-cloudflare-bans" ) + + +class ArgumentConflict(NextcordException): + ... diff --git a/nextcord/type_sheet.py b/nextcord/type_sheet.py index 02216fd..d1a5b1b 100644 --- a/nextcord/type_sheet.py +++ b/nextcord/type_sheet.py @@ -1,22 +1,21 @@ -""" -The MIT License (MIT) -Copyright (c) 2021-present vcokltfre & tag-epic -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -""" +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/nextcord/types/allowed_mentions.py b/nextcord/types/allowed_mentions.py new file mode 100644 index 0000000..344242a --- /dev/null +++ b/nextcord/types/allowed_mentions.py @@ -0,0 +1,77 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from __future__ import annotations + +from logging import getLogger +from typing import TYPE_CHECKING, Optional, Union + +if TYPE_CHECKING: + from .snowflake import Snowflake + + +Role, User = None, None # TODO: DEFINE and import + +logger = getLogger(__name__) + + +class AllowedMentions: + def __init__( + self, + *, + everyone: bool = False, + roles: Union[bool, list[Role], Role] = False, + users: Union[bool, User, list[User]] = True, + replied_user: Optional[bool] = None, + ): + self.everyone = everyone + self.roles = roles + self.users = users + self.replied_user = replied_user + + def to_dict(self) -> dict[str, Union[list[str], list[Snowflake], bool]]: + allowed: dict[str, Union[list[str], list[Snowflake], bool]] = {"parse": []} + if self.everyone: + allowed["parse"].append("everyone") + + if isinstance(self.roles, bool) and self.roles: + allowed["parse"].append("roles") + elif isinstance(self.roles, list): + allowed["roles"] = [r.id for r in self.roles] + elif isinstance(self.roles, Role): + allowed["roles"] = [self.roles.id] + + if isinstance(self.users, bool) and self.roles: + allowed["parse"].append("users") + elif isinstance(self.users, list): + allowed["users"] = [u.id for u in self.roles] + elif isinstance(self.users, User): + allowed["users"] = [self.users.id] + + if self.replied_user: + allowed["replied_user"] = bool(self.replied_user) + + return allowed + + @classmethod + def none(cls) -> AllowedMentions: + return cls(everyone=False, roles=False, users=False, replied_user=False) + + @classmethod + def all(cls) -> AllowedMentions: + return cls(everyone=True, roles=True, users=True, replied_user=True) diff --git a/nextcord/types/channel.py b/nextcord/types/channel.py new file mode 100644 index 0000000..93f22ef --- /dev/null +++ b/nextcord/types/channel.py @@ -0,0 +1,32 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from __future__ import annotations + +from logging import getLogger +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from ..client.state import State + +logger = getLogger(__name__) + + +class Channel: + def __init__(self, state: State, data: dict): + pass diff --git a/nextcord/types/embed.py b/nextcord/types/embed.py new file mode 100644 index 0000000..7b26037 --- /dev/null +++ b/nextcord/types/embed.py @@ -0,0 +1,217 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from __future__ import annotations + +import typing +from dataclasses import asdict, dataclass, is_dataclass +from datetime import datetime +from logging import getLogger +from typing import TYPE_CHECKING, Optional, Union + +if TYPE_CHECKING: + ... + +logger = getLogger(__name__) + + +@dataclass(frozen=True) +class EmbedFile: + url: str + proxy_url: Optional[str] = None + height: Optional[int] = None + width: Optional[int] = None + + +@dataclass(frozen=True) +class EmbedThumbnail(EmbedFile): + ... + + +@dataclass(frozen=True) +class EmbedVideo(EmbedFile): + url: Optional[str] = None + + +@dataclass(frozen=True) +class EmbedImage(EmbedFile): + ... + + +@dataclass(frozen=True) +class EmbedProvider: + name: Optional[str] = None + url: Optional[str] = None + + +@dataclass(frozen=True) +class EmbedAuthor: + name: str + url: Optional[str] = None + icon_url: Optional[str] = None + proxy_icon_url: Optional[str] = None + + +@dataclass(frozen=True) +class EmbedFooter: + text: str + icon_url: Optional[str] = None + proxy_icon_url: Optional[str] = None + + +class EmbedField: + def __init__(self, name: str, value: str, *, inline: Optional[bool] = None): + self.name = str(name) + self.value = str(value) + self.inline = bool(inline) + + +class Embed: + _special = {"provider": EmbedProvider, "video": EmbedVideo} + __slots__ = ( + "title", + "description", + "url", + "timestamp", + "color", + "footer", + "image", + "thumbnail", + "author", + "fields", + "_provider", + "_video", + ) + + if TYPE_CHECKING: + _video: EmbedVideo + _provider: EmbedProvider + + def __init__( + self, + *, + title: Optional[str] = None, + description: Optional[str] = None, + url: Optional[str] = None, + timestamp: Optional[datetime] = None, + color: Optional[int] = None, + footer: Optional[EmbedFooter] = None, + image: Optional[EmbedImage] = None, + thumbnail: Optional[EmbedThumbnail] = None, + author: Optional[EmbedAuthor] = None, + fields: Optional[list[EmbedField]] = [], + ): + self.title = str(title) if title is not None else None + self.description = str(description) if description is not None else None + self.url = str(url) if url is not None else None + self.color = int(color) if color is not None else None + self.timestamp = timestamp + + self.footer = footer if isinstance(footer, EmbedFooter) else None + self.image = image if isinstance(image, EmbedImage) else None + self.thumbnail = thumbnail if isinstance(thumbnail, EmbedThumbnail) else None + self.author = author if isinstance(author, EmbedAuthor) else None + self.fields = fields if isinstance(fields, list) else [] + + self._provider = None + self._video = None + + def add_field( + self, + name: str, + value: str, + *, + inline: Optional[bool] = None, + position: Optional[int] = None, + ) -> None: + if position is not None: + self.fields.insert(position, EmbedField(name, value, inline=inline)) + else: + self.fields.append(EmbedField(name, value, inline=inline)) + + def edit_field( + self, + index: int, + name: Optional[str] = None, + value: Optional[str] = None, + *, + inline: Optional[bool] = None, + ) -> None: + if name is not None: + self.fields[index].name = name + if value is not None: + self.fields[index].value = value + if inline is not None: + self.fields[index].inline = inline + + def remove_field(self, *, index: int) -> None: + try: + del self.fields[index] + except IndexError: + pass + + @property + def video(self) -> Optional[EmbedVideo]: + return self._video + + @property + def provider(self) -> Optional[EmbedProvider]: + return self._provider + + @classmethod + def from_dict(cls, data: dict): + embed = cls() + typehints = typing.get_type_hints(cls.__init__) + for key, value in data.items(): + if key in typehints: + constr = typing.get_args(typehints[key])[0] + elif key in cls._special: + constr = cls._special[key] + else: + continue # Invalid key, not implemented + + if value is None: + val = None + elif isinstance(value, dict): + val = constr(**value) + else: + val = constr(value) + + if key in cls._special: + setattr(embed, "_" + key, val) + elif key in embed.__slots__: + setattr(embed, key, val) + else: + continue # TODO: Unknown key, should it raise an error? + + return embed + + def to_dict(self) -> dict[str, Union[str, dict[str, str]]]: + data = {} + for key in self.__slots__: + key = key.lstrip("_") + if key in self._special: + val = getattr(self, "_" + key) + else: + val = getattr(self, key) + if is_dataclass(val): + val = asdict(val) + + data[key] = val + + return data diff --git a/nextcord/types/protocols/__init__.py b/nextcord/types/protocols/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nextcord/types/protocols/base_user.py b/nextcord/types/protocols/base_user.py new file mode 100644 index 0000000..86b5b9c --- /dev/null +++ b/nextcord/types/protocols/base_user.py @@ -0,0 +1,124 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from __future__ import annotations + +from logging import getLogger +from typing import TYPE_CHECKING, Optional, Protocol + +if TYPE_CHECKING: + from ...client.state import State + from ..snowflake import Snowflake + + +logger = getLogger(__name__) + + +class UserProtocol(Protocol): + __slots__ = ( + "id", + "username", + "discriminator", + "_avatar", + "bot", + "system", + "_banner", + "_accent_color", + "_premium_type", + "_public_flags", + "_state", + ) + + if TYPE_CHECKING: + id: Snowflake + username: str + discriminator: str + _avatar: Optional[str] + + bot: bool + system: bool + _banner: Optional[str] + _accent_color: Optional[int] + _public_flags: int + _state: State + + def __init__(self, *, state: State, data: dict): + self._state = state + self._update(data) + + def _update(self, data: dict) -> None: + self.id = data["id"] + self.username = data["username"] + self.discriminator = data["discriminator"] + self._avatar = data["avatar"] + + self.bot = data.get("bot") + self.system = data.get("system") + self._banner = data.get("banner") + self._accent_color = data.get("accent_color") + self._public_flags = data.get("public_flags") + + +class ClientUser(UserProtocol): + __slots__ = ("mfa_enabled", "locale", "verified", "email", "flags", "bio") + + if TYPE_CHECKING: + mfa_enabled: bool + locale: str + verified: bool + flags: int + bio: str + + def __init__(self, state: State, data: dict): + super().__init__(state=state, data=data) + + def _update(self, data: dict): + super()._update(data) + self.mfa_enabled = data.get("mfa_enabled") + self.locale = data.get("locale") + self.verified = data.get("verified") + self.flags = data.get("flags") + self.bio = data.get("bio") + + async def edit(self, *, username: Optional[str] = None, avatar: Optional[bytes] = None) -> None: + payload = {} + if username is not None: + payload["username"] = username + + if avatar is not None: + payload["avatar"] = ... # TODO: convert bytes to base64 image format + + await self._state.http # TODO: HTTP not implemented yet + + async def get_guilds( + self, + *, + before: Optional[Snowflake] = None, + after: Optional[Snowflake] = None, + limit: Optional[int] = None, + ): + ... + + async def _get_guild_member(self, *, guild_id: Snowflake): + ... + + async def _leave_guild(self, *, guild_id: Snowflake): + ... + + async def _create_dm(self, *, recipient_id: Snowflake): + ... diff --git a/nextcord/types/snowflake.py b/nextcord/types/snowflake.py new file mode 100644 index 0000000..d6e182e --- /dev/null +++ b/nextcord/types/snowflake.py @@ -0,0 +1,20 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +Snowflake = int +SnowflakeList = list[Snowflake] diff --git a/nextcord/types/user.py b/nextcord/types/user.py new file mode 100644 index 0000000..56fd39b --- /dev/null +++ b/nextcord/types/user.py @@ -0,0 +1,28 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from __future__ import annotations + +from logging import getLogger +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + ... + + +logger = getLogger(__name__) diff --git a/nextcord/utils.py b/nextcord/utils.py index 361ceca..560f937 100644 --- a/nextcord/utils.py +++ b/nextcord/utils.py @@ -1,22 +1,20 @@ -""" -The MIT License (MIT) -Copyright (c) 2021-present vcokltfre & tag-epic -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -""" +# The MIT License (MIT) +# Copyright (c) 2021-present vcokltfre & tag-epic +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. __all__ = ("json",) diff --git a/tests/embed.py b/tests/embed.py new file mode 100644 index 0000000..addb787 --- /dev/null +++ b/tests/embed.py @@ -0,0 +1,19 @@ +from nextcord.types.embed import Embed, EmbedFooter, EmbedProvider + +embed = Embed( + title="The title", description="The description", footer=EmbedFooter(text="hey", icon_url="https://discord.com/") +) +embed._provider = EmbedProvider(name="Discord", url="https://discord.com/") + +data = embed.to_dict() +print(data) +embed2 = Embed.from_dict(data) +print(embed2, dir(embed2)) +for a in dir(embed2): + if not a.startswith("__"): + print(a, getattr(embed2, a)) + +data2 = embed2.to_dict() + +print(data2) +assert data == data2