Source code for discord_http.user

from typing import TYPE_CHECKING, Optional, Union, Any

from . import utils
from .asset import Asset
from .colour import Colour
from .embeds import Embed
from .enums import DefaultAvatarType
from .file import File
from .flags import PublicFlags
from .mentions import AllowedMentions
from .object import PartialBase
from .response import ResponseType, MessageResponse
from .view import View

if TYPE_CHECKING:
    from .channel import DMChannel
    from .http import DiscordAPI
    from .message import Message

MISSING = utils.MISSING

__all__ = (
    "UserClient",
    "PartialUser",
    "User",
)


[docs] class PartialUser(PartialBase): def __init__( self, *, state: "DiscordAPI", id: int ): super().__init__(id=int(id)) self._state = state def __repr__(self) -> str: return f"<PartialUser id={self.id}>" @property def mention(self) -> str: """ `str`: Returns a string that allows you to mention the user """ return f"<@!{self.id}>"
[docs] async def send( self, content: Optional[str] = MISSING, *, channel_id: Optional[int] = MISSING, embed: Optional[Embed] = MISSING, embeds: Optional[list[Embed]] = MISSING, file: Optional[File] = MISSING, files: Optional[list[File]] = MISSING, view: Optional[View] = MISSING, tts: Optional[bool] = False, type: Union[ResponseType, int] = 4, allowed_mentions: Optional[AllowedMentions] = MISSING, delete_after: Optional[float] = None ) -> "Message": """ Send a message to the user Parameters ---------- content: `Optional[str]` Content of the message channel_id: `Optional[int]` Channel ID to send the message to, if not provided, it will create a DM channel embed: `Optional[Embed]` Embed of the message embeds: `Optional[list[Embed]]` Embeds of the message file: `Optional[File]` File of the message files: `Optional[Union[list[File], File]]` Files of the message view: `Optional[View]` Components of the message tts: `bool` Whether the message should be sent as TTS type: `Optional[ResponseType]` Which type of response should be sent allowed_mentions: `Optional[AllowedMentions]` Allowed mentions of the message delete_after: `Optional[float]` How long to wait before deleting the message Returns ------- `Message` The message that was sent """ if channel_id is MISSING: fetch_channel = await self.create_dm() channel_id = fetch_channel.id payload = MessageResponse( content, embed=embed, embeds=embeds, file=file, files=files, view=view, tts=tts, type=type, allowed_mentions=allowed_mentions, ) r = await self._state.query( "POST", f"/channels/{channel_id}/messages", data=payload.to_multipart(is_request=True), headers={"Content-Type": payload.content_type} ) from .message import Message _msg = Message( state=self._state, data=r.response ) if delete_after is not None: await _msg.delete(delay=float(delete_after)) return _msg
[docs] async def create_dm(self) -> "DMChannel": """ `DMChannel`: Creates a DM channel with the user """ r = await self._state.query( "POST", "/users/@me/channels", json={"recipient_id": self.id} ) from .channel import DMChannel return DMChannel( state=self._state, data=r.response )
[docs] async def fetch(self) -> "User": """ `User`: Fetches the user """ r = await self._state.query( "GET", f"/users/{self.id}" ) return User( state=self._state, data=r.response )
@property def default_avatar(self) -> Asset: """ `Asset`: Returns the default avatar of the user """ return Asset._from_default_avatar( self._state, (self.id >> 22) % len(DefaultAvatarType) )
[docs] class User(PartialUser): def __init__( self, *, state: "DiscordAPI", data: dict ): super().__init__(state=state, id=int(data["id"])) self.avatar: Optional[Asset] = None self.banner: Optional[Asset] = None self.name: str = data["username"] self.bot: bool = data.get("bot", False) self.system: bool = data.get("system", False) # This section is ONLY here because bots still have a discriminator self.discriminator: Optional[str] = data.get("discriminator", None) if self.discriminator == "0": # Instead of showing "0", just make it None.... self.discriminator = None self.accent_colour: Optional[Colour] = None self.banner_colour: Optional[Colour] = None self.avatar_decoration: Optional[Asset] = None self.global_name: Optional[str] = data.get("global_name", None) self.public_flags: Optional[PublicFlags] = None # This might change a lot self.clan: Optional[dict] = data.get("clan", None) self._from_data(data) def __repr__(self) -> str: return ( f"<User id={self.id} name='{self.name}' " f"global_name='{self.global_name}'>" ) def __str__(self) -> str: if self.discriminator: return f"{self.name}#{self.discriminator}" return self.name def _from_data(self, data: dict): if data.get("avatar", None): self.avatar = Asset._from_avatar( self._state, self.id, data["avatar"] ) if data.get("banner", None): self.banner = Asset._from_banner( self._state, self.id, data["banner"] ) if data.get("accent_color", None): self.accent_colour = Colour(data["accent_color"]) if data.get("banner_color", None): self.banner_colour = Colour.from_hex(data["banner_color"]) if data.get("avatar_decoration", None): self.avatar_decoration = Asset._from_avatar_decoration( self._state, data["avatar_decoration"] ) if data.get("public_flags", None): self.public_flags = PublicFlags(data["public_flags"]) @property def global_avatar(self) -> Optional[Asset]: """ `Asset`: Alias for `User.avatar` """ return self.avatar @property def display_name(self) -> str: """ `str`: Returns the user's display name """ return self.global_name or self.name @property def display_avatar(self) -> Optional[Asset]: """ `Optional[Asset]`: Returns the display avatar of the member """ return self.avatar or self.default_avatar
[docs] class UserClient(User): def __init__( self, *, state: "DiscordAPI", data: dict ): super().__init__(state=state, data=data) self.verified: bool = data.get("verified", False) def __repr__(self) -> str: return f"<UserClient id={self.id} name='{self.name}'>"
[docs] async def edit( self, *, username: str | None = MISSING, avatar: bytes | None = MISSING, banner: bytes | None = MISSING, ) -> "UserClient": payload: dict[str, Any] = {} if username is not MISSING: payload["username"] = username if avatar is not MISSING: if avatar is not None: payload["avatar"] = utils.bytes_to_base64(avatar) else: payload["avatar"] = None if banner is not MISSING: if banner is not None: payload["banner"] = utils.bytes_to_base64(banner) else: payload["banner"] = None r = await self._state.query( "PATCH", "/users/@me", json=payload ) return UserClient( state=self._state, data=r.response )