From 4bbaff8d574b5ea109ebf23a161f63db3f4b1c22 Mon Sep 17 00:00:00 2001 From: grey-cat-1908 Date: Tue, 15 Mar 2022 21:11:16 +0300 Subject: [PATCH] so, after senpai commits, i decided to use APINullable; Added caching bot-user in ready listener; Added fetch_user method --- melisa/client.py | 20 ++++++++++++- melisa/core/__init__.py | 2 +- melisa/listeners/ready.py | 2 ++ melisa/models/user/presence.py | 53 +++++++++++++++++----------------- melisa/models/user/user.py | 53 ++++++++++++++++++++-------------- 5 files changed, 81 insertions(+), 49 deletions(-) diff --git a/melisa/client.py b/melisa/client.py index a324950..97e26cb 100644 --- a/melisa/client.py +++ b/melisa/client.py @@ -1,11 +1,14 @@ +from . import exceptions +from .models import User from .models.app import Shard +from .utils import Snowflake from .utils.types import Coro from .core.http import HTTPClient from .core.gateway import GatewayBotInfo import asyncio -from typing import Dict, List +from typing import Dict, List, Union class Client: @@ -15,6 +18,7 @@ class Client: self._events = {} self.guilds = [] + self.user = None self.loop = asyncio.get_event_loop() @@ -89,4 +93,18 @@ class Client: asyncio.ensure_future(inited_shard.launch(activity=self._activity, status=self._status), loop=self.loop) self.loop.run_forever() + async def fetch_user(self, user_id: Union[Snowflake, str, int]): + """ + Fetch User from the Discord API (by id). + Parameters + ---------- + user_id : :class:`Union[Snowflake, str, int]` + Id of user to fetch + """ + + # ToDo: Update cache if USER_CACHING enabled. + + data = await self.http.get(f"users/{user_id}") + + return User.from_dict(data) diff --git a/melisa/core/__init__.py b/melisa/core/__init__.py index ac12363..0abc29c 100644 --- a/melisa/core/__init__.py +++ b/melisa/core/__init__.py @@ -1 +1 @@ -from .gateway import Gateway \ No newline at end of file +from .gateway import Gateway diff --git a/melisa/listeners/ready.py b/melisa/listeners/ready.py index 681eb93..1279f85 100644 --- a/melisa/listeners/ready.py +++ b/melisa/listeners/ready.py @@ -1,6 +1,7 @@ from __future__ import annotations from ..utils.types import Coro +from ..models.user import User async def on_ready_listener(self, gateway, payload: dict): @@ -9,6 +10,7 @@ async def on_ready_listener(self, gateway, payload: dict): guilds = payload.get("guilds") self.guilds = dict(map(lambda i: (i["id"], None), guilds)) + self.user = User.from_dict(payload.get("user")) custom_listener = self._events.get("on_ready") diff --git a/melisa/models/user/presence.py b/melisa/models/user/presence.py index c1bfaff..058fc97 100644 --- a/melisa/models/user/presence.py +++ b/melisa/models/user/presence.py @@ -4,6 +4,7 @@ from typing import Optional, Tuple, List, Literal from ...utils import Snowflake from ...utils import APIObjectBase +from ...utils.types import APINullable class BasePresence: @@ -55,8 +56,8 @@ class ActivityTimestamp(BasePresence, APIObjectBase): end: Optional[:class:`int`] Unix time (in milliseconds) of when the activity ends """ - start: Optional[int] = None - end: Optional[int] = None + start: APINullable[int] = None + end: APINullable[int] = None @dataclass(repr=False) @@ -73,8 +74,8 @@ class ActivityEmoji(BasePresence, APIObjectBase): Whether this emoji is animated """ name: str - id: Optional[Snowflake] = None - animated: Optional[bool] = None + id: APINullable[Snowflake] = None + animated: APINullable[bool] = None @dataclass(repr=False) @@ -88,8 +89,8 @@ class ActivityParty(BasePresence, APIObjectBase): size: Optional[Tuple[:class:`int`, :class:`int`]] Array of two integers (current_size, max_size) """ - id: Optional[str] = None - size: Optional[Tuple[int, int]] = None + id: APINullable[str] = None + size: APINullable[Tuple[int, int]] = None @dataclass(repr=False) @@ -107,10 +108,10 @@ class ActivityAssets(BasePresence, APIObjectBase): small_text: Optional[:class:`str`] text displayed when hovering over the small image of the activity """ - large_image: Optional[str] = None - large_text: Optional[str] = None - small_image: Optional[str] = None - small_text: Optional[str] = None + large_image: APINullable[str] = None + large_text: APINullable[str] = None + small_image: APINullable[str] = None + small_text: APINullable[str] = None @dataclass(repr=False) @@ -126,9 +127,9 @@ class ActivitySecrets(BasePresence, APIObjectBase): match: Optional[:class:`str`] The secret for a specific instanced match """ - join: Optional[str] = None - spectate: Optional[str] = None - match_: Optional[str] = None + join: APINullable[str] = None + spectate: APINullable[str] = None + match_: APINullable[str] = None class ActivityFlags(BasePresence, APIObjectBase): @@ -208,18 +209,18 @@ class Activity(BasePresence, APIObjectBase): type: ActivityType created_at: int - url: Optional[str] = None - timestamps: Optional[ActivityTimestamp] = None - application_id: Optional[Snowflake] = None - details: Optional[str] = None - state: Optional[str] = None - emoji: Optional[ActivityEmoji] = None - party: Optional[ActivityParty] = None - assets: Optional[ActivityAssets] = None - secrets: Optional[ActivitySecrets] = None - instance: Optional[bool] = None - flags: Optional[ActivityFlags] = None - buttons: Optional[List[ActivityButton]] = None + url: APINullable[str] = None + timestamps: APINullable[ActivityTimestamp] = None + application_id: APINullable[Snowflake] = None + details: APINullable[str] = None + state: APINullable[str] = None + emoji: APINullable[ActivityEmoji] = None + party: APINullable[ActivityParty] = None + assets: APINullable[ActivityAssets] = None + secrets: APINullable[ActivitySecrets] = None + instance: APINullable[bool] = None + flags: APINullable[ActivityFlags] = None + buttons: APINullable[List[ActivityButton]] = None @dataclass(repr=False) @@ -237,7 +238,7 @@ class BotActivity(BasePresence, APIObjectBase): name: str type: ActivityType - url: Optional[str] = None + url: APINullable[str] = None class StatusType(Enum): diff --git a/melisa/models/user/user.py b/melisa/models/user/user.py index afd6eb9..4fe02ac 100644 --- a/melisa/models/user/user.py +++ b/melisa/models/user/user.py @@ -5,6 +5,7 @@ from dataclasses import dataclass from typing import Optional from ...utils.api_object import APIObjectBase +from ...utils.types import APINullable from ...utils.snowflake import Snowflake @@ -85,6 +86,7 @@ class UserFlags(IntEnum): def __int__(self): return self.value + class VisibilityTypes(IntEnum): """The type of connection visibility. @@ -102,6 +104,7 @@ class VisibilityTypes(IntEnum): def __int__(self): return self.value + @dataclass(repr=False) class User(APIObjectBase): """User Structure @@ -140,25 +143,26 @@ class User(APIObjectBase): the public flags on a user's account """ - id: Optional[Snowflake] = None - username: Optional[str] = None - discriminator: Optional[str] = None - avatar: Optional[str] = None - bot: Optional[bool] = None - system: Optional[bool] = None - mfa_enabled: Optional[bool] = None - banner: Optional[str] = None - accent_color: Optional[int] = None - local: Optional[str] = None - verified: Optional[bool] = None - email: Optional[str] = None - flags: Optional[int] = None - premium_type: Optional[int] = None - public_flags: Optional[int] = None - + id: APINullable[Snowflake] = None + username: APINullable[str] = None + discriminator: APINullable[str] = None + avatar: APINullable[str] = None + bot: APINullable[bool] = None + system: APINullable[bool] = None + mfa_enabled: APINullable[bool] = None + banner: APINullable[str] = None + accent_color: APINullable[int] = None + local: APINullable[str] = None + verified: APINullable[bool] = None + email: APINullable[str] = None + premium_type: APINullable[int] = None + public_flags: APINullable[int] = None @property def premium(self) -> Optional[PremiumTypes]: + """APINullable[:class:`~melisa.models.user.user.PremiumTypes`]: The + user their premium type in a usable enum. + """ return ( None if self.premium_type is None @@ -167,19 +171,26 @@ class User(APIObjectBase): @property def flags(self) -> Optional[UserFlags]: + """Flags of user""" return( None if self.flags is None else UserFlags(self.flags) ) - @property - def mention(self): - return "<@!{}>".format(self.id) + def __str__(self): + """String representation of the User object""" + return self.username + "#" + self.discriminator @property - def get_avatar_url(self): + def mention(self): + """:class:`str`: The user's mention string. (<@id>)""" + return "<@{}>".format(self.id) + + @property + def avatar_url(self): + """Avatar url (from the discord cdn server)""" return ( "https://cdn.discordapp.com/avatars/{}/{}.png".format(self.id, self.avatar), "?size=1024" - ) \ No newline at end of file + )