diff --git a/EpikCord/application.py b/EpikCord/application.py index d6fea815..8d9a153d 100644 --- a/EpikCord/application.py +++ b/EpikCord/application.py @@ -7,13 +7,48 @@ class InstallParams: + """ + Attributes: + ---------- + scopes: :class:`` + The scopes that are used by the install params. + permissions: :class:`Epikcord.flags.Permission` + The permissions that the application requires. + """ def __init__(self, data: InstallParamsData): + """ + Parameters: + ---------- + data: :class:`discord_typings.InstallParamsData` + The data used to construct the class. + Note + ---- + Should never be manually constructed. + """ self.scopes = data["scopes"] self.permissions = Permissions(int(data["permissions"])) class TeamMember: + """ + Attributes: + ---------- + membership_state: :class:`discord_typings.TeamMembershipState` + The status of the membership of this member. + permissions: :class:`list[str]` + The permissions that they have. As of now this is always ["*"]. + team_id: :class:`int` + The id of the team. + user: :class:`User` + The user object for this member. + """ def __init__(self, data: TeamMemberData): + """ + Parameters: + ---------- + data: :class:`discord_typings.TeamMemberData` + The data of the TeamMember + """ self.membership_state = TeamMembershipState(data["membership_state"]) self.permissions = data["permissions"] self.team_id = int(data["team_id"]) @@ -22,7 +57,27 @@ def __init__(self, data: TeamMemberData): class Team: + """ + Attributes: + ---------- + icon: :class:`` + The icon of the team. + id: :class:`int` + The id of the team. + members: :class:`list` + The members in the team. + name: :class:`str` + The name of the team. + owner_user_id: :class:`int` + The owner id of the team. + """ def __init__(self, data: TeamData): + """ + Parameters: + ---------- + data: :class:`discord_typings.TeamData` + The data of the team + """ self.icon = data["icon"] self.id = int(data["id"]) self.members = [TeamMember(member) for member in data["members"]] @@ -31,7 +86,59 @@ def __init__(self, data: TeamData): class Application: + """ + Attributes: + ---------- + id: :class:`int` + The id of the application + name: :class:`str` + The name of the application + icon: :class:`` + The icon of the application + description: :class:`str` + The description of the application + rpc_origins: :class:`list[str]` + A list of RPC origins for the application + bot_public: :class:`bool` + A boolean representing if the bot is public + bot_require_code_grant: :class:`bool` + A boolean representing if the bot requires a code grant + terms_of_service_url: :class:`str` + The Terms of Service url. + privacy_policy_url = :class:`str` + The Privacy Policy url + owner: :class:`` + The owner of the application. + verify_key: :class:`str` + A string used to verify signatures for receiving interactions via HTTP. + team: :class:`Epikcord.application.Team` + The team the application is in. + guild_id: :class:`int` + The id of guild + primary_sku_id: :class:`int` + ... + slug: :class:`` + ... + cover_image: :class:`` + ... + flags: :class:`Epikcord.flags.ApplicationFlags` + ... + tags: :class:`` + ... + install_params: :class:`Optional[InstallParams]` + The install parameters of the application. + self.custom_install_url: :class:`Optional[str]` + The URL to redirect users to once they click "Add Bot" in the client. + self.role_connections_verification_url: :class:`Optional[str]` + The URL that users are redirected to if they want to link a role. + """ def __init__(self, data: ApplicationData): + """ + Paramters: + --------- + data: :class:`discord_typings.ApplicationData` + The data of the Application + """ self.id = int(data["id"]) self.name = data["name"] self.icon = data.get("icon") diff --git a/EpikCord/exceptions.py b/EpikCord/exceptions.py index 3d7642b7..18d4b766 100644 --- a/EpikCord/exceptions.py +++ b/EpikCord/exceptions.py @@ -14,7 +14,31 @@ class LocatedError: class HTTPException(EpikCordException): + """Exception raised when the webserver throws an error. + + This inherits from :class:`EpikcordException`. + + + Attributes + ---------- + body: :class:`dict` + ... + code: :class:`` + The error code. + message: :class:`` + The message it returns. + errors: :class:`dict` + The errors it returns. + errors_list: :class:`list` + ... + """ def __init__(self, data: Dict): + """ + Parameters: + ---------- + data: :class:`typing.Dict` + ... + """ self.body = data self.code = data.get("code") self.message = data.get("message") @@ -28,7 +52,21 @@ def __init__(self, data: Dict): ) def extract_errors(self, d, key_path=None): - """Get _errors key from the given dictionary.""" + """Get _errors key from the given dictionary. + + Parameters: + ---------- + d: :class:`dict` + ... + key_path: :class:`` + ... + + Returns + ------- + ...: + ... + + """ if key_path is None: key_path = [] @@ -53,50 +91,111 @@ def extract_errors(self, d, key_path=None): class NotFound(HTTPException): + """Exception that's raised when status code 404 occurs. + + This inherits from :class:`HTTPException`. + """ ... class Forbidden(HTTPException): + """Exception that's raised when status code 403 occurs. + + This inherits from :class:`HTTPException`. + """ ... class Unauthorized(HTTPException): + """Exception raised due to + + This inherits from :class:`HTTPException`. + """ ... class BadRequest(HTTPException): + """Exception raised due to + + This inherits from :class:`HTTPException`. + """ ... class TooManyRetries(EpikCordException): + """Exception raised when + + This inherits from :class:`EpikCordException`. + """ ... class ClosedWebSocketConnection(EpikCordException): + """Exception raised due to + + This inherits from :class:`EpikCordException`. + """ ... class DisallowedIntents(ClosedWebSocketConnection): + """Exception raised due to + + This inherits from :class:`EpikCordException`. + """ ... class InvalidIntents(ClosedWebSocketConnection): + """Exception raised when an intent does not exist. + + This inherits from :class:`EpikCordException`. + """ ... class InvalidToken(ClosedWebSocketConnection): + """Exception raised when fails to log you in from improper credentials. + + This inherits from :class:`EpikCordException`. + """ ... class GatewayRateLimited(ClosedWebSocketConnection): + """Exception that's raised when status code 429 occurs. + + This inherits from :class:`EpikCordException`. + """ ... class ShardingRequired(ClosedWebSocketConnection): + """Exception raised due to + + This inherits from :class:`EpikCordException`. + """ ... class UnknownMimeType(EpikCordException): + """Exception raised due to + + This inherits from :class:`EpikCordException`. + + Attributes: + ---------- + filename: :class:`` + The name of the file. + message: :class:`str` + The message raised by error. + """ def __init__(self, filename): + """ + Parameters: + ---------- + filename: :class:`` + The name of the file. + """ self.filename = filename self.message = f"Cannot resolve mime type for file `{filename}`." diff --git a/EpikCord/file.py b/EpikCord/file.py index 4c8ae83d..eb8cc291 100644 --- a/EpikCord/file.py +++ b/EpikCord/file.py @@ -8,7 +8,38 @@ class Attachment: + """ + Attributes: + ---------- + id: :class:`int` + The id of the attachment. + filename: :class:`str` + The name of the attachment. + size: :class:`` + The size of the attachment. + url: :class:`str` + The url to the attachment. + proxy_url: :class:`str` + The proxy url to the attachment. + description: :class:`str` + The description of the attachment. + content_type: :class:`` + ... + height: :class:`int` + The height of the attachment. + width: :class:`int` + The width of the attachment. + ephemeral: :class:`bool` + If the file was sent with an ephemeral. + """ def __init__(self, data: AttachmentData): + """ + Parameters: + ---------- + data: :class:`discord_typings.AttachmentData` + The data containing all the information of the file. + """ + self.id = int(data["id"]) self.filename = data["filename"] self.size = data["size"] @@ -23,6 +54,20 @@ def __init__(self, data: AttachmentData): class File: + """ + Attributes: + ---------- + filename: :class:`str` + The name of the file. + contents: :class:`io.IOBase` + The bytes inside the file. + description: Optional[str] + The description of the file. + mine_type: :class:`str` + ... + spolier (optional): :class:`bool` + If the file is sent with a spolier. + """ def __init__( self, filename: str, @@ -39,12 +84,16 @@ def __init__( The filename of the file. contents: io.IOBase The contents of the file. - mime_type: Optional[str] + mime_type: str The mime type of the file. If not provided, it will be guessed. spoiler: bool Whether the file is a spoiler. description: Optional[str] The description of the file. + + Raises: + ------ + UnkownMineType: When mine type is None """ self.contents: io.IOBase = contents self.mime_type = mime_type or _guess_mime_type(filename) @@ -52,13 +101,21 @@ def __init__( if self.mime_type is None: raise UnknownMimeType(filename) - if spoiler: - self.filename = f"SPOILER_{filename}" - else: - self.filename = filename + self.filename = f"SPOILER_{filename}" if spoiler else filename self.description: Optional[str] = description def _guess_mime_type(filename: str) -> Optional[str]: + """ + Parameters: + ---------- + filename: :class:`str` + The name of the file + + Returns: + ------- + mine_type: :class:`` + ... + """ mime_type, _encoding = mimetypes.guess_type(filename) return mime_type diff --git a/EpikCord/flags.py b/EpikCord/flags.py index 47d4f4c5..4da5d91d 100644 --- a/EpikCord/flags.py +++ b/EpikCord/flags.py @@ -6,6 +6,12 @@ class Flag: + """ + Attributes: + ---------- + turned_on: :class:`typing.List` + The number of the flag turned on. + """ class_flags: Dict[str, int] def __init_subclass__(cls) -> None: @@ -14,6 +20,13 @@ def __init_subclass__(cls) -> None: } def __init__(self, value: int = ALL_VALUE_DISABLED, **kwargs): + """ + Parameters: + ---------- + value: :class:`int` + The value of the flag. + + """ self.turned_on: List[str] = [ k.upper() for k, a in kwargs.items() @@ -26,6 +39,13 @@ def __init__(self, value: int = ALL_VALUE_DISABLED, **kwargs): @property def value(self) -> int: + """ + The value of all of the flags. + + Returns: + ------- + + """ return sum( flag for key, flag in self.class_flags.items() @@ -36,9 +56,7 @@ def __getattribute__(self, __name: str) -> Any: original = super().__getattribute__ key = type(self).class_flags.get(__name.upper()) - if key is None: - return original(__name) - return __name in original("turned_on") + return original(__name) if key is None else __name in original("turned_on") def __setattr__(self, __name: str, __value: Any) -> None: __upper_name = __name.upper() diff --git a/EpikCord/guild.py b/EpikCord/guild.py index 49090497..7aeabad1 100644 --- a/EpikCord/guild.py +++ b/EpikCord/guild.py @@ -9,7 +9,45 @@ class GuildMember: + """ + Attributes: + ---------- + client: :class:`Epikcord.client.Client`. + ... + user: :class:`` + The user itself. + nick: :class:`str` + The nickname the user uses in the guild. + avatar: :class:`str` + The avatar of the user in the guild. + roles: :class:`` + The roles the user has. + joined_at: :class:`datetime.datetime.fromisoformat` + When the client joined the guild. + premium_since: :class:`datetime.datetime.fromisoformat` + How long the member has premium. + deaf: :class:`` + If the member is deafend. + mute: :class:`` + If the member is muted. + flags: :class:`` + The flags the member has. + pending: :class:`` + ... + permissions: :class:`` + The permissions the member has. + communication_disabled_until: :class:`` + How long the member has communication disabled. + """ def __init__(self, client: Client, data: GuildMemberData): + """ + Parameters: + ----------- + client: :class:`Epikcord.client.Client` + The bot itself. + data: :class:`discord_typings.GuildMemberData + The data about the member in the guild. + """ self.client = client self.user = instance_or_none( User, data.get("user"), client, data.get("user"), ignore_value=True @@ -41,26 +79,76 @@ def __init__(self, client: Client, data: GuildMemberData): class RoleTags: + """ + Attributes: + ---------- + bot_id: :class:`int` + ... + integration_id: :class:`int` + ... + premium_subscriber: :class:`bool` + ... + available_for_purchase: :class:`bool` + ... + guild_connections: :class:`bool` + ... + """ def __init__(self, data: RoleTagsData): + """ + Parameters: + ---------- + data: :class:`discord_typings.RoleTagsData` + Data containing Role Tags. + """ self._data = data self.bot_id = int_or_none(data.get("bot_id")) self.integration_id = int_or_none(data.get("integration_id")) - self.premium_subscriber = ( - True if data.get("premium_subscriber") else False - ) + self.premium_subscriber = bool(data.get("premium_subscriber")) self.subscription_listing_id = int_or_none( data.get("subscription_listing_id") ) - self.available_for_purchase = ( - True if data.get("available_for_purchase") else False - ) - self.guild_connections = ( - True if data.get("guild_connections") else False - ) + self.available_for_purchase = bool(data.get("available_for_purchase")) + self.guild_connections = bool(data.get("guild_connections")) class Role: + """ + Attributes: + ---------- + client: :class:`Epikcord.client.Client` + The bot itself. + id: :class:`int` + The id of the role. + name: :class:`str` + The name given to the role. + color: :class:`int` + The color given to the role. + hoist: :class:`` + ... + icon: :class:`` + The icon of the role. + unicode_emoji: :class:`` + ... + position: :class:`` + The position the role is in (in a hierarchy). + permissions: :class:`Epikcord.flags.Permissions` + The permission the role has. + managed: :class:`` + ... + mentionable: :class:`` + If the role is pingable + tags: :class:`Epikcord.guild.RoleTags` + ... + """ def __init__(self, client: Client, data: RoleData): + """ + Parameters: + ----------- + client: :class:`Epikcord.client.Client` + The bot itself + data: :class:`discord_typings.RoleData` + Data containing about the role + """ self.client = client self._data = data self.id = int(data["id"]) diff --git a/EpikCord/user.py b/EpikCord/user.py index b33e9d1d..008211e9 100644 --- a/EpikCord/user.py +++ b/EpikCord/user.py @@ -6,7 +6,49 @@ class User: + """ + Attributes: + ---------- + client: :class:`Epikcord.client.Client` + The bot itself + id: :class:`int` + The id of the user + username: :class:`str` + The name of the user + discriminator: :class:`int` + The 4 digit number on user's profile + avatar: :class:`` + The avatar ... + bot: :class:`bool` + If the user is a bot + system: :class:`` + ... + mfa_enabled: :class:`bool` + If the user enabled mfa (Multi factor authentication) + banner: :class:`` + The banner on the user's profile + accent_color: :class:`` + The accent color the user has on his profile + locale: :class:`Epikcord.utils.Locale` + ... + verified: :class:`bool` + If the user is verified + email: :class:`str` + The email of the user + premium_type: :class:`Epikcord.utils.PremiumType` + The type of premium the user has (Nitro Basic or Nitro) + public_flags: :class:`Epikcord.flags.UserFlags` + The public flags the user has + """ def __init__(self, client: Client, data: UserData): + """ + Parameters: + ----------- + client: :class:`Epikcord.client.Client` + The bot itself + data: :class:`discord_typings.UserData` + Data containing about the user + """ self.client = client self.id = int(data["id"]) self.username = data["username"] diff --git a/EpikCord/utils/enums.py b/EpikCord/utils/enums.py index 8d525e8f..4b31e794 100644 --- a/EpikCord/utils/enums.py +++ b/EpikCord/utils/enums.py @@ -105,6 +105,22 @@ class HTTPCodes(StatusCode): @classmethod def _missing_(cls, value: object) -> HTTPCodes: + """ + Parameters: + ---------- + value : :class:`object` + HTTP Status Code + + Raises: + ------ + ValueError: When the value isn't a valid HTTP status code + ValueError: The HTTP status code isn't documented + + Returns: + ------- + HTTPCodes.SERVER_ERROR + A server error code + """ if not isinstance(value, int): raise ValueError(f"{value} is not a valid HTTP status code.") @@ -343,6 +359,17 @@ class JSONErrorCodes(StatusCode): @classmethod def _missing_(cls, value: object) -> JSONErrorCodes: + """ + Parameters: + ---------- + value : :class:`object` + HTTP Status Code + + Returns: + ------- + JSONErrorCodes.GENERAL_ERROR + A JSON error + """ logger = getLogger("EpikCord.exceptions") logger.warning(f"Unknown JSON error code: {value}") return cls.GENERAL_ERROR diff --git a/EpikCord/utils/loose.py b/EpikCord/utils/loose.py index faa1f69d..75219138 100644 --- a/EpikCord/utils/loose.py +++ b/EpikCord/utils/loose.py @@ -65,8 +65,7 @@ def clean_url(url: str, version: int) -> str: async def extract_content(response: aiohttp.ClientResponse) -> Dict[str, Any]: if response.headers["Content-Type"] != "application/json": return {} - data = await response.json() - return data + return await response.json() def singleton(cls): @@ -159,9 +158,7 @@ def instance_or_none( ) -> Optional[T]: if value is None: return None - if ignore_value: - return cls(*args, **kwargs) - return cls(value, *args, **kwargs) + return cls(*args, **kwargs) if ignore_value else cls(value, *args, **kwargs) int_or_none = partial(instance_or_none, cls=int)