Browse Source

[typing] Type-hint client.py

pull/7135/head
Josh 4 years ago
committed by GitHub
parent
commit
7601d6cec3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 205
      discord/client.py

205
discord/client.py

@ -29,7 +29,7 @@ import logging
import signal import signal
import sys import sys
import traceback import traceback
from typing import Any, Generator, List, Optional, Sequence, TYPE_CHECKING, TypeVar, Union from typing import Any, Callable, Coroutine, Dict, Generator, Iterable, List, Optional, Sequence, TYPE_CHECKING, Tuple, TypeVar, Union
import aiohttp import aiohttp
@ -38,12 +38,13 @@ from .invite import Invite
from .template import Template from .template import Template
from .widget import Widget from .widget import Widget
from .guild import Guild from .guild import Guild
from .emoji import Emoji
from .channel import _channel_factory from .channel import _channel_factory
from .enums import ChannelType from .enums import ChannelType
from .mentions import AllowedMentions from .mentions import AllowedMentions
from .errors import * from .errors import *
from .enums import Status, VoiceRegion from .enums import Status, VoiceRegion
from .flags import ApplicationFlags from .flags import ApplicationFlags, Intents
from .gateway import * from .gateway import *
from .activity import BaseActivity, create_activity from .activity import BaseActivity, create_activity
from .voice_client import VoiceClient from .voice_client import VoiceClient
@ -58,16 +59,24 @@ from .appinfo import AppInfo
from .ui.view import View from .ui.view import View
from .stage_instance import StageInstance from .stage_instance import StageInstance
if TYPE_CHECKING:
from .abc import SnowflakeTime, PrivateChannel, GuildChannel, Snowflake
from .channel import DMChannel
from .user import ClientUser
from .message import Message
from .member import Member
from .voice_client import VoiceProtocol
__all__ = ( __all__ = (
'Client', 'Client',
) )
if TYPE_CHECKING: Coro = TypeVar('Coro', bound=Callable[..., Coroutine[Any, Any, Any]])
from .abc import SnowflakeTime
log = logging.getLogger(__name__)
def _cancel_tasks(loop): log: logging.Logger = logging.getLogger(__name__)
def _cancel_tasks(loop: asyncio.AbstractEventLoop) -> None:
tasks = {t for t in asyncio.all_tasks(loop=loop) if not t.done()} tasks = {t for t in asyncio.all_tasks(loop=loop) if not t.done()}
if not tasks: if not tasks:
@ -90,7 +99,7 @@ def _cancel_tasks(loop):
'task': task 'task': task
}) })
def _cleanup_loop(loop): def _cleanup_loop(loop: asyncio.AbstractEventLoop) -> None:
try: try:
_cancel_tasks(loop) _cancel_tasks(loop)
loop.run_until_complete(loop.shutdown_asyncgens()) loop.run_until_complete(loop.shutdown_asyncgens())
@ -116,7 +125,7 @@ class Client:
The :class:`asyncio.AbstractEventLoop` to use for asynchronous operations. The :class:`asyncio.AbstractEventLoop` to use for asynchronous operations.
Defaults to ``None``, in which case the default event loop is used via Defaults to ``None``, in which case the default event loop is used via
:func:`asyncio.get_event_loop()`. :func:`asyncio.get_event_loop()`.
connector: :class:`aiohttp.BaseConnector` connector: Optional[:class:`aiohttp.BaseConnector`]
The connector to use for connection pooling. The connector to use for connection pooling.
proxy: Optional[:class:`str`] proxy: Optional[:class:`str`]
Proxy URL. Proxy URL.
@ -181,31 +190,36 @@ class Client:
loop: :class:`asyncio.AbstractEventLoop` loop: :class:`asyncio.AbstractEventLoop`
The event loop that the client uses for asynchronous operations. The event loop that the client uses for asynchronous operations.
""" """
def __init__(self, *, loop=None, **options): def __init__(
self.ws = None self,
self.loop = asyncio.get_event_loop() if loop is None else loop *,
self._listeners = {} loop: Optional[asyncio.AbstractEventLoop] = None,
self.shard_id = options.get('shard_id') **options: Any,
self.shard_count = options.get('shard_count') ):
self.ws: DiscordWebSocket = None # type: ignore
connector = options.pop('connector', None) self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() if loop is None else loop
proxy = options.pop('proxy', None) self._listeners: Dict[str, List[Tuple[asyncio.Future, Callable[..., bool]]]] = {}
proxy_auth = options.pop('proxy_auth', None) self.shard_id: Optional[int] = options.get('shard_id')
unsync_clock = options.pop('assume_unsync_clock', True) self.shard_count: Optional[int] = options.get('shard_count')
self.http = HTTPClient(connector, proxy=proxy, proxy_auth=proxy_auth, unsync_clock=unsync_clock, loop=self.loop)
connector: Optional[aiohttp.BaseConnector] = options.pop('connector', None)
self._handlers = { proxy: Optional[str] = options.pop('proxy', None)
proxy_auth: Optional[aiohttp.BasicAuth] = options.pop('proxy_auth', None)
unsync_clock: bool = options.pop('assume_unsync_clock', True)
self.http: HTTPClient = HTTPClient(connector, proxy=proxy, proxy_auth=proxy_auth, unsync_clock=unsync_clock, loop=self.loop)
self._handlers: Dict[str, Callable] = {
'ready': self._handle_ready 'ready': self._handle_ready
} }
self._hooks = { self._hooks: Dict[str, Callable] = {
'before_identify': self._call_before_identify_hook 'before_identify': self._call_before_identify_hook
} }
self._connection = self._get_state(**options) self._connection: ConnectionState = self._get_state(**options)
self._connection.shard_count = self.shard_count self._connection.shard_count = self.shard_count
self._closed = False self._closed: bool = False
self._ready = asyncio.Event() self._ready: asyncio.Event = asyncio.Event()
self._connection._get_websocket = self._get_websocket self._connection._get_websocket = self._get_websocket
self._connection._get_client = lambda: self self._connection._get_client = lambda: self
@ -215,18 +229,18 @@ class Client:
# internals # internals
def _get_websocket(self, guild_id=None, *, shard_id=None): def _get_websocket(self, guild_id: Optional[int] = None, *, shard_id: Optional[int] = None) -> DiscordWebSocket:
return self.ws return self.ws
def _get_state(self, **options): def _get_state(self, **options: Any) -> ConnectionState:
return ConnectionState(dispatch=self.dispatch, handlers=self._handlers, return ConnectionState(dispatch=self.dispatch, handlers=self._handlers,
hooks=self._hooks, http=self.http, loop=self.loop, **options) hooks=self._hooks, http=self.http, loop=self.loop, **options)
def _handle_ready(self): def _handle_ready(self) -> None:
self._ready.set() self._ready.set()
@property @property
def latency(self): def latency(self) -> float:
""":class:`float`: Measures latency between a HEARTBEAT and a HEARTBEAT_ACK in seconds. """:class:`float`: Measures latency between a HEARTBEAT and a HEARTBEAT_ACK in seconds.
This could be referred to as the Discord WebSocket protocol latency. This could be referred to as the Discord WebSocket protocol latency.
@ -234,7 +248,7 @@ class Client:
ws = self.ws ws = self.ws
return float('nan') if not ws else ws.latency return float('nan') if not ws else ws.latency
def is_ws_ratelimited(self): def is_ws_ratelimited(self) -> bool:
""":class:`bool`: Whether the websocket is currently rate limited. """:class:`bool`: Whether the websocket is currently rate limited.
This can be useful to know when deciding whether you should query members This can be useful to know when deciding whether you should query members
@ -247,22 +261,22 @@ class Client:
return False return False
@property @property
def user(self): def user(self) -> Optional[ClientUser]:
"""Optional[:class:`.ClientUser`]: Represents the connected client. ``None`` if not logged in.""" """Optional[:class:`.ClientUser`]: Represents the connected client. ``None`` if not logged in."""
return self._connection.user return self._connection.user
@property @property
def guilds(self): def guilds(self) -> List[Guild]:
"""List[:class:`.Guild`]: The guilds that the connected client is a member of.""" """List[:class:`.Guild`]: The guilds that the connected client is a member of."""
return self._connection.guilds return self._connection.guilds
@property @property
def emojis(self): def emojis(self) -> List[Emoji]:
"""List[:class:`.Emoji`]: The emojis that the connected client has.""" """List[:class:`.Emoji`]: The emojis that the connected client has."""
return self._connection.emojis return self._connection.emojis
@property @property
def cached_messages(self): def cached_messages(self) -> Sequence[Message]:
"""Sequence[:class:`.Message`]: Read-only list of messages the connected client has cached. """Sequence[:class:`.Message`]: Read-only list of messages the connected client has cached.
.. versionadded:: 1.1 .. versionadded:: 1.1
@ -270,7 +284,7 @@ class Client:
return utils.SequenceProxy(self._connection._messages or []) return utils.SequenceProxy(self._connection._messages or [])
@property @property
def private_channels(self): def private_channels(self) -> List[PrivateChannel]:
"""List[:class:`.abc.PrivateChannel`]: The private channels that the connected client is participating on. """List[:class:`.abc.PrivateChannel`]: The private channels that the connected client is participating on.
.. note:: .. note::
@ -281,7 +295,7 @@ class Client:
return self._connection.private_channels return self._connection.private_channels
@property @property
def voice_clients(self): def voice_clients(self) -> List[VoiceProtocol]:
"""List[:class:`.VoiceProtocol`]: Represents a list of voice connections. """List[:class:`.VoiceProtocol`]: Represents a list of voice connections.
These are usually :class:`.VoiceClient` instances. These are usually :class:`.VoiceClient` instances.
@ -289,7 +303,7 @@ class Client:
return self._connection.voice_clients return self._connection.voice_clients
@property @property
def application_id(self): def application_id(self) -> Optional[int]:
"""Optional[:class:`int`]: The client's application ID. """Optional[:class:`int`]: The client's application ID.
If this is not passed via ``__init__`` then this is retrieved If this is not passed via ``__init__`` then this is retrieved
@ -306,11 +320,11 @@ class Client:
""" """
return self._connection.application_flags # type: ignore return self._connection.application_flags # type: ignore
def is_ready(self): def is_ready(self) -> bool:
""":class:`bool`: Specifies if the client's internal cache is ready for use.""" """:class:`bool`: Specifies if the client's internal cache is ready for use."""
return self._ready.is_set() return self._ready.is_set()
async def _run_event(self, coro, event_name, *args, **kwargs): async def _run_event(self, coro: Callable[..., Coroutine[Any, Any, Any]], event_name: str, *args: Any, **kwargs: Any) -> None:
try: try:
await coro(*args, **kwargs) await coro(*args, **kwargs)
except asyncio.CancelledError: except asyncio.CancelledError:
@ -321,12 +335,12 @@ class Client:
except asyncio.CancelledError: except asyncio.CancelledError:
pass pass
def _schedule_event(self, coro, event_name, *args, **kwargs): def _schedule_event(self, coro: Callable[..., Coroutine[Any, Any, Any]], event_name: str, *args: Any, **kwargs: Any) -> asyncio.Task:
wrapped = self._run_event(coro, event_name, *args, **kwargs) wrapped = self._run_event(coro, event_name, *args, **kwargs)
# Schedules the task # Schedules the task
return asyncio.create_task(wrapped, name=f'discord.py: {event_name}') return asyncio.create_task(wrapped, name=f'discord.py: {event_name}')
def dispatch(self, event, *args, **kwargs): def dispatch(self, event: str, *args: Any, **kwargs: Any) -> None:
log.debug('Dispatching event %s', event) log.debug('Dispatching event %s', event)
method = 'on_' + event method = 'on_' + event
@ -366,7 +380,7 @@ class Client:
else: else:
self._schedule_event(coro, method, *args, **kwargs) self._schedule_event(coro, method, *args, **kwargs)
async def on_error(self, event_method, *args, **kwargs): async def on_error(self, event_method: str, *args: Any, **kwargs: Any) -> None:
"""|coro| """|coro|
The default error handler provided by the client. The default error handler provided by the client.
@ -380,13 +394,13 @@ class Client:
# hooks # hooks
async def _call_before_identify_hook(self, shard_id, *, initial=False): async def _call_before_identify_hook(self, shard_id: Optional[int], *, initial: bool = False) -> None:
# This hook is an internal hook that actually calls the public one. # This hook is an internal hook that actually calls the public one.
# It allows the library to have its own hook without stepping on the # It allows the library to have its own hook without stepping on the
# toes of those who need to override their own hook. # toes of those who need to override their own hook.
await self.before_identify_hook(shard_id, initial=initial) await self.before_identify_hook(shard_id, initial=initial)
async def before_identify_hook(self, shard_id, *, initial=False): async def before_identify_hook(self, shard_id: Optional[int], *, initial: bool = False) -> None:
"""|coro| """|coro|
A hook that is called before IDENTIFYing a session. This is useful A hook that is called before IDENTIFYing a session. This is useful
@ -410,7 +424,7 @@ class Client:
# login state management # login state management
async def login(self, token): async def login(self, token: str) -> None:
"""|coro| """|coro|
Logs in the client with the specified credentials. Logs in the client with the specified credentials.
@ -435,7 +449,7 @@ class Client:
log.info('logging in using static token') log.info('logging in using static token')
await self.http.static_login(token.strip()) await self.http.static_login(token.strip())
async def connect(self, *, reconnect=True): async def connect(self, *, reconnect: bool = True) -> None:
"""|coro| """|coro|
Creates a websocket connection and lets the websocket listen Creates a websocket connection and lets the websocket listen
@ -519,7 +533,7 @@ class Client:
# This is apparently what the official Discord client does. # This is apparently what the official Discord client does.
ws_params.update(sequence=self.ws.sequence, resume=True, session=self.ws.session_id) ws_params.update(sequence=self.ws.sequence, resume=True, session=self.ws.session_id)
async def close(self): async def close(self) -> None:
"""|coro| """|coro|
Closes the connection to Discord. Closes the connection to Discord.
@ -531,7 +545,7 @@ class Client:
for voice in self.voice_clients: for voice in self.voice_clients:
try: try:
await voice.disconnect() await voice.disconnect(force=True)
except Exception: except Exception:
# if an error happens during disconnects, disregard it. # if an error happens during disconnects, disregard it.
pass pass
@ -542,7 +556,7 @@ class Client:
await self.http.close() await self.http.close()
self._ready.clear() self._ready.clear()
def clear(self): def clear(self) -> None:
"""Clears the internal state of the bot. """Clears the internal state of the bot.
After this, the bot can be considered "re-opened", i.e. :meth:`is_closed` After this, the bot can be considered "re-opened", i.e. :meth:`is_closed`
@ -554,7 +568,7 @@ class Client:
self._connection.clear() self._connection.clear()
self.http.recreate() self.http.recreate()
async def start(self, token, *, reconnect=True): async def start(self, token: str, *, reconnect: bool = True) -> None:
"""|coro| """|coro|
A shorthand coroutine for :meth:`login` + :meth:`connect`. A shorthand coroutine for :meth:`login` + :meth:`connect`.
@ -567,7 +581,7 @@ class Client:
await self.login(token) await self.login(token)
await self.connect(reconnect=reconnect) await self.connect(reconnect=reconnect)
def run(self, *args, **kwargs): def run(self, *args: Any, **kwargs: Any) -> None:
"""A blocking call that abstracts away the event loop """A blocking call that abstracts away the event loop
initialisation from you. initialisation from you.
@ -629,19 +643,19 @@ class Client:
# properties # properties
def is_closed(self): def is_closed(self) -> bool:
""":class:`bool`: Indicates if the websocket connection is closed.""" """:class:`bool`: Indicates if the websocket connection is closed."""
return self._closed return self._closed
@property @property
def activity(self): def activity(self) -> Optional[BaseActivity]:
"""Optional[:class:`.BaseActivity`]: The activity being used upon """Optional[:class:`.BaseActivity`]: The activity being used upon
logging in. logging in.
""" """
return create_activity(self._connection._activity) return create_activity(self._connection._activity)
@activity.setter @activity.setter
def activity(self, value): def activity(self, value: Optional[BaseActivity]) -> None:
if value is None: if value is None:
self._connection._activity = None self._connection._activity = None
elif isinstance(value, BaseActivity): elif isinstance(value, BaseActivity):
@ -650,7 +664,7 @@ class Client:
raise TypeError('activity must derive from BaseActivity.') raise TypeError('activity must derive from BaseActivity.')
@property @property
def allowed_mentions(self): def allowed_mentions(self) -> Optional[AllowedMentions]:
"""Optional[:class:`~discord.AllowedMentions`]: The allowed mention configuration. """Optional[:class:`~discord.AllowedMentions`]: The allowed mention configuration.
.. versionadded:: 1.4 .. versionadded:: 1.4
@ -658,14 +672,14 @@ class Client:
return self._connection.allowed_mentions return self._connection.allowed_mentions
@allowed_mentions.setter @allowed_mentions.setter
def allowed_mentions(self, value): def allowed_mentions(self, value: Optional[AllowedMentions]) -> None:
if value is None or isinstance(value, AllowedMentions): if value is None or isinstance(value, AllowedMentions):
self._connection.allowed_mentions = value self._connection.allowed_mentions = value
else: else:
raise TypeError(f'allowed_mentions must be AllowedMentions not {value.__class__!r}') raise TypeError(f'allowed_mentions must be AllowedMentions not {value.__class__!r}')
@property @property
def intents(self): def intents(self) -> Intents:
""":class:`~discord.Intents`: The intents configured for this connection. """:class:`~discord.Intents`: The intents configured for this connection.
.. versionadded:: 1.5 .. versionadded:: 1.5
@ -675,11 +689,11 @@ class Client:
# helpers/getters # helpers/getters
@property @property
def users(self): def users(self) -> List[User]:
"""List[:class:`~discord.User`]: Returns a list of all the users the bot can see.""" """List[:class:`~discord.User`]: Returns a list of all the users the bot can see."""
return list(self._connection._users.values()) return list(self._connection._users.values())
def get_channel(self, id): def get_channel(self, id: int) -> Optional[Union[GuildChannel, PrivateChannel]]:
"""Returns a channel with the given ID. """Returns a channel with the given ID.
Parameters Parameters
@ -716,7 +730,7 @@ class Client:
if isinstance(channel, StageChannel): if isinstance(channel, StageChannel):
return channel.instance return channel.instance
def get_guild(self, id): def get_guild(self, id) -> Optional[Guild]:
"""Returns a guild with the given ID. """Returns a guild with the given ID.
Parameters Parameters
@ -731,7 +745,7 @@ class Client:
""" """
return self._connection._get_guild(id) return self._connection._get_guild(id)
def get_user(self, id): def get_user(self, id) -> Optional[User]:
"""Returns a user with the given ID. """Returns a user with the given ID.
Parameters Parameters
@ -746,7 +760,7 @@ class Client:
""" """
return self._connection.get_user(id) return self._connection.get_user(id)
def get_emoji(self, id): def get_emoji(self, id) -> Optional[Emoji]:
"""Returns an emoji with the given ID. """Returns an emoji with the given ID.
Parameters Parameters
@ -761,7 +775,7 @@ class Client:
""" """
return self._connection.get_emoji(id) return self._connection.get_emoji(id)
def get_all_channels(self): def get_all_channels(self) -> Generator[GuildChannel, None, None]:
"""A generator that retrieves every :class:`.abc.GuildChannel` the client can 'access'. """A generator that retrieves every :class:`.abc.GuildChannel` the client can 'access'.
This is equivalent to: :: This is equivalent to: ::
@ -785,7 +799,7 @@ class Client:
for guild in self.guilds: for guild in self.guilds:
yield from guild.channels yield from guild.channels
def get_all_members(self): def get_all_members(self) -> Generator[Member, None, None]:
"""Returns a generator with every :class:`.Member` the client can see. """Returns a generator with every :class:`.Member` the client can see.
This is equivalent to: :: This is equivalent to: ::
@ -804,14 +818,20 @@ class Client:
# listeners/waiters # listeners/waiters
async def wait_until_ready(self): async def wait_until_ready(self) -> None:
"""|coro| """|coro|
Waits until the client's internal cache is all ready. Waits until the client's internal cache is all ready.
""" """
await self._ready.wait() await self._ready.wait()
def wait_for(self, event, *, check=None, timeout=None): def wait_for(
self,
event: str,
*,
check: Optional[Callable[..., bool]] = None,
timeout: Optional[float] = None,
) -> Any:
"""|coro| """|coro|
Waits for a WebSocket event to be dispatched. Waits for a WebSocket event to be dispatched.
@ -911,7 +931,7 @@ class Client:
# event registration # event registration
def event(self, coro): def event(self, coro: Coro) -> Coro:
"""A decorator that registers an event to listen to. """A decorator that registers an event to listen to.
You can find more info about the events on the :ref:`documentation below <discord-api-events>`. You can find more info about the events on the :ref:`documentation below <discord-api-events>`.
@ -940,7 +960,13 @@ class Client:
log.debug('%s has successfully been registered as an event', coro.__name__) log.debug('%s has successfully been registered as an event', coro.__name__)
return coro return coro
async def change_presence(self, *, activity=None, status=None, afk=False): async def change_presence(
self,
*,
activity: Optional[BaseActivity] = None,
status: Optional[Status] = None,
afk: bool = False,
):
"""|coro| """|coro|
Changes the client's presence. Changes the client's presence.
@ -972,16 +998,15 @@ class Client:
""" """
if status is None: if status is None:
status = 'online' status_str = 'online'
status_enum = Status.online status = Status.online
elif status is Status.offline: elif status is Status.offline:
status = 'invisible' status_str = 'invisible'
status_enum = Status.offline status = Status.offline
else: else:
status_enum = status status_str = str(status)
status = str(status)
await self.ws.change_presence(activity=activity, status=status, afk=afk) await self.ws.change_presence(activity=activity, status=status_str, afk=afk)
for guild in self._connection.guilds: for guild in self._connection.guilds:
me = guild.me me = guild.me
@ -993,11 +1018,17 @@ class Client:
else: else:
me.activities = () me.activities = ()
me.status = status_enum me.status = status
# Guild stuff # Guild stuff
def fetch_guilds(self, *, limit: int = 100, before: SnowflakeTime = None, after: SnowflakeTime = None) -> List[Guild]: def fetch_guilds(
self,
*,
limit: Optional[int] = 100,
before: SnowflakeTime = None,
after: SnowflakeTime = None
) -> List[Guild]:
"""Retrieves an :class:`.AsyncIterator` that enables receiving your guilds. """Retrieves an :class:`.AsyncIterator` that enables receiving your guilds.
.. note:: .. note::
@ -1052,7 +1083,7 @@ class Client:
""" """
return GuildIterator(self, limit=limit, before=before, after=after) return GuildIterator(self, limit=limit, before=before, after=after)
async def fetch_template(self, code): async def fetch_template(self, code: Union[Template, str]) -> Template:
"""|coro| """|coro|
Gets a :class:`.Template` from a discord.new URL or code. Gets a :class:`.Template` from a discord.new URL or code.
@ -1078,7 +1109,7 @@ class Client:
data = await self.http.get_template(code) data = await self.http.get_template(code)
return Template(data=data, state=self._connection) # type: ignore return Template(data=data, state=self._connection) # type: ignore
async def fetch_guild(self, guild_id): async def fetch_guild(self, guild_id: int) -> Guild:
"""|coro| """|coro|
Retrieves a :class:`.Guild` from an ID. Retrieves a :class:`.Guild` from an ID.
@ -1112,7 +1143,7 @@ class Client:
data = await self.http.get_guild(guild_id) data = await self.http.get_guild(guild_id)
return Guild(data=data, state=self._connection) return Guild(data=data, state=self._connection)
async def create_guild(self, name: str, region: Optional[VoiceRegion] = None, icon: Any = None, *, code: str = None): async def create_guild(self, name: str, region: Optional[VoiceRegion] = None, icon: Any = None, *, code: str = None) -> Guild:
"""|coro| """|coro|
Creates a :class:`.Guild`. Creates a :class:`.Guild`.
@ -1259,7 +1290,7 @@ class Client:
# Miscellaneous stuff # Miscellaneous stuff
async def fetch_widget(self, guild_id): async def fetch_widget(self, guild_id: int) -> Widget:
"""|coro| """|coro|
Gets a :class:`.Widget` from a guild ID. Gets a :class:`.Widget` from a guild ID.
@ -1289,7 +1320,7 @@ class Client:
return Widget(state=self._connection, data=data) return Widget(state=self._connection, data=data)
async def application_info(self): async def application_info(self) -> AppInfo:
"""|coro| """|coro|
Retrieves the bot's application information. Retrieves the bot's application information.
@ -1309,7 +1340,7 @@ class Client:
data['rpc_origins'] = None data['rpc_origins'] = None
return AppInfo(self._connection, data) return AppInfo(self._connection, data)
async def fetch_user(self, user_id): async def fetch_user(self, user_id: int) -> User:
"""|coro| """|coro|
Retrieves a :class:`~discord.User` based on their ID. Retrieves a :class:`~discord.User` based on their ID.
@ -1340,7 +1371,7 @@ class Client:
data = await self.http.get_user(user_id) data = await self.http.get_user(user_id)
return User(state=self._connection, data=data) return User(state=self._connection, data=data)
async def fetch_channel(self, channel_id): async def fetch_channel(self, channel_id: int) -> Union[GuildChannel, PrivateChannel]:
"""|coro| """|coro|
Retrieves a :class:`.abc.GuildChannel` or :class:`.abc.PrivateChannel` with the specified ID. Retrieves a :class:`.abc.GuildChannel` or :class:`.abc.PrivateChannel` with the specified ID.
@ -1382,7 +1413,7 @@ class Client:
return channel return channel
async def fetch_webhook(self, webhook_id): async def fetch_webhook(self, webhook_id: int) -> Webhook:
"""|coro| """|coro|
Retrieves a :class:`.Webhook` with the specified ID. Retrieves a :class:`.Webhook` with the specified ID.
@ -1404,7 +1435,7 @@ class Client:
data = await self.http.get_webhook(webhook_id) data = await self.http.get_webhook(webhook_id)
return Webhook.from_state(data, state=self._connection) return Webhook.from_state(data, state=self._connection)
async def create_dm(self, user): async def create_dm(self, user: Snowflake) -> DMChannel:
"""|coro| """|coro|
Creates a :class:`.DMChannel` with this user. Creates a :class:`.DMChannel` with this user.

Loading…
Cancel
Save