aboutsummaryrefslogtreecommitdiff
path: root/discord/client.py
diff options
context:
space:
mode:
authorRapptz <[email protected]>2018-06-10 18:09:14 -0400
committerRapptz <[email protected]>2018-06-10 18:10:00 -0400
commitf25091efe1281aebe70189c61f9cac405b21a72f (patch)
treed0d13dad1a89de9f45845a36ea475098b7a0b494 /discord/client.py
parentAdd Message.jump_to_url (diff)
downloaddiscord.py-f25091efe1281aebe70189c61f9cac405b21a72f.tar.xz
discord.py-f25091efe1281aebe70189c61f9cac405b21a72f.zip
Drop support for Python 3.4 and make minimum version 3.5.2.
Diffstat (limited to 'discord/client.py')
-rw-r--r--discord/client.py128
1 files changed, 53 insertions, 75 deletions
diff --git a/discord/client.py b/discord/client.py
index 0434d1e2..a46f1637 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -48,7 +48,6 @@ import sys, re
import signal
from collections import namedtuple
-PY35 = sys.version_info >= (3, 5)
log = logging.getLogger(__name__)
AppInfo = namedtuple('AppInfo', 'id name description icon owner')
@@ -139,12 +138,10 @@ class Client:
# internals
- @asyncio.coroutine
- def _syncer(self, guilds):
- yield from self.ws.request_sync(guilds)
+ async def _syncer(self, guilds):
+ await self.ws.request_sync(guilds)
- @asyncio.coroutine
- def _chunker(self, guild):
+ async def _chunker(self, guild):
try:
guild_id = guild.id
except AttributeError:
@@ -159,7 +156,7 @@ class Client:
}
}
- yield from self.ws.send_as_json(payload)
+ await self.ws.send_as_json(payload)
def handle_ready(self):
self._ready.set()
@@ -218,15 +215,14 @@ class Client:
""":obj:`bool`: Specifies if the client's internal cache is ready for use."""
return self._ready.is_set()
- @asyncio.coroutine
- def _run_event(self, coro, event_name, *args, **kwargs):
+ async def _run_event(self, coro, event_name, *args, **kwargs):
try:
- yield from coro(*args, **kwargs)
+ await coro(*args, **kwargs)
except asyncio.CancelledError:
pass
except Exception:
try:
- yield from self.on_error(event_name, *args, **kwargs)
+ await self.on_error(event_name, *args, **kwargs)
except asyncio.CancelledError:
pass
@@ -276,10 +272,9 @@ class Client:
except AttributeError:
pass
else:
- compat.create_task(self._run_event(coro, method, *args, **kwargs), loop=self.loop)
+ asyncio.ensure_future(self._run_event(coro, method, *args, **kwargs), loop=self.loop)
- @asyncio.coroutine
- def on_error(self, event_method, *args, **kwargs):
+ async def on_error(self, event_method, *args, **kwargs):
"""|coro|
The default error handler provided by the client.
@@ -291,8 +286,7 @@ class Client:
print('Ignoring exception in {}'.format(event_method), file=sys.stderr)
traceback.print_exc()
- @asyncio.coroutine
- def request_offline_members(self, *guilds):
+ async def request_offline_members(self, *guilds):
"""|coro|
Requests previously offline members from the guild to be filled up
@@ -318,12 +312,11 @@ class Client:
if any(not g.large or g.unavailable for g in guilds):
raise InvalidArgument('An unavailable or non-large guild was passed.')
- yield from self._connection.request_offline_members(guilds)
+ await self._connection.request_offline_members(guilds)
# login state management
- @asyncio.coroutine
- def login(self, token, *, bot=True):
+ async def login(self, token, *, bot=True):
"""|coro|
Logs in the client with the specified credentials.
@@ -350,34 +343,31 @@ class Client:
"""
log.info('logging in using static token')
- yield from self.http.static_login(token, bot=bot)
+ await self.http.static_login(token, bot=bot)
self._connection.is_bot = bot
- @asyncio.coroutine
- def logout(self):
+ async def logout(self):
"""|coro|
Logs out of Discord and closes all connections.
"""
- yield from self.close()
+ await self.close()
- @asyncio.coroutine
- def _connect(self):
+ async def _connect(self):
coro = DiscordWebSocket.from_client(self, shard_id=self.shard_id)
- self.ws = yield from asyncio.wait_for(coro, timeout=180.0, loop=self.loop)
+ self.ws = await asyncio.wait_for(coro, timeout=180.0, loop=self.loop)
while True:
try:
- yield from self.ws.poll_event()
+ await self.ws.poll_event()
except ResumeWebSocket as e:
log.info('Got a request to RESUME the websocket.')
coro = DiscordWebSocket.from_client(self, shard_id=self.shard_id,
session=self.ws.session_id,
sequence=self.ws.sequence,
resume=True)
- self.ws = yield from asyncio.wait_for(coro, timeout=180.0, loop=self.loop)
+ self.ws = await asyncio.wait_for(coro, timeout=180.0, loop=self.loop)
- @asyncio.coroutine
- def connect(self, *, reconnect=True):
+ async def connect(self, *, reconnect=True):
"""|coro|
Creates a websocket connection and lets the websocket listen
@@ -405,7 +395,7 @@ class Client:
backoff = ExponentialBackoff()
while not self.is_closed():
try:
- yield from self._connect()
+ await self._connect()
except (OSError,
HTTPException,
GatewayNotFound,
@@ -416,7 +406,7 @@ class Client:
websockets.WebSocketProtocolError) as e:
if not reconnect:
- yield from self.close()
+ await self.close()
if isinstance(e, ConnectionClosed) and e.code == 1000:
# clean close, don't re-raise this
return
@@ -431,15 +421,14 @@ class Client:
# regardless and rely on is_closed instead
if isinstance(e, ConnectionClosed):
if e.code != 1000:
- yield from self.close()
+ await self.close()
raise
retry = backoff.delay()
log.exception("Attempting a reconnect in %.2fs", retry)
- yield from asyncio.sleep(retry, loop=self.loop)
+ await asyncio.sleep(retry, loop=self.loop)
- @asyncio.coroutine
- def close(self):
+ async def close(self):
"""|coro|
Closes the connection to discord.
@@ -451,16 +440,16 @@ class Client:
for voice in self.voice_clients:
try:
- yield from voice.disconnect()
+ await voice.disconnect()
except:
# if an error happens during disconnects, disregard it.
pass
if self.ws is not None and self.ws.open:
- yield from self.ws.close()
+ await self.ws.close()
- yield from self.http.close()
+ await self.http.close()
self._ready.clear()
def clear(self):
@@ -475,8 +464,7 @@ class Client:
self._connection.clear()
self.http.recreate()
- @asyncio.coroutine
- def start(self, *args, **kwargs):
+ async def start(self, *args, **kwargs):
"""|coro|
A shorthand coroutine for :meth:`login` + :meth:`connect`.
@@ -484,8 +472,8 @@ class Client:
bot = kwargs.pop('bot', True)
reconnect = kwargs.pop('reconnect', True)
- yield from self.login(*args, bot=bot)
- yield from self.connect(reconnect=reconnect)
+ await self.login(*args, bot=bot)
+ await self.connect(reconnect=reconnect)
def _do_cleanup(self):
log.info('Cleaning up event loop.')
@@ -493,7 +481,7 @@ class Client:
if loop.is_closed():
return # we're already cleaning up
- task = compat.create_task(self.close(), loop=loop)
+ task = asyncio.ensure_future(self.close(), loop=loop)
def _silence_gathered(fut):
try:
@@ -558,7 +546,7 @@ class Client:
loop.add_signal_handler(signal.SIGINT, self._do_cleanup)
loop.add_signal_handler(signal.SIGTERM, self._do_cleanup)
- task = compat.create_task(self.start(*args, **kwargs), loop=loop)
+ task = asyncio.ensure_future(self.start(*args, **kwargs), loop=loop)
def stop_loop_on_finish(fut):
loop.stop()
@@ -661,13 +649,12 @@ class Client:
# listeners/waiters
- @asyncio.coroutine
- def wait_until_ready(self):
+ async def wait_until_ready(self):
"""|coro|
Waits until the client's internal cache is all ready.
"""
- yield from self._ready.wait()
+ await self._ready.wait()
def wait_for(self, event, *, check=None, timeout=None):
"""|coro|
@@ -751,7 +738,7 @@ class Client:
:ref:`event reference <discord-api-events>`.
"""
- future = compat.create_future(self.loop)
+ future = self.loop.create_future()
if check is None:
def _check(*args):
return True
@@ -782,8 +769,7 @@ class Client:
Using the basic :meth:`event` decorator: ::
@client.event
- @asyncio.coroutine
- def on_ready():
+ async def on_ready():
print('Ready!')
Saving characters by using the :meth:`async_event` decorator: ::
@@ -808,8 +794,7 @@ class Client:
return self.event(coro)
- @asyncio.coroutine
- def change_presence(self, *, activity=None, status=None, afk=False):
+ async def change_presence(self, *, activity=None, status=None, afk=False):
"""|coro|
Changes the client's presence.
@@ -851,7 +836,7 @@ class Client:
status_enum = status
status = str(status)
- yield from self.ws.change_presence(activity=activity, status=status, afk=afk)
+ await self.ws.change_presence(activity=activity, status=status, afk=afk)
for guild in self._connection.guilds:
me = guild.me
@@ -863,8 +848,7 @@ class Client:
# Guild stuff
- @asyncio.coroutine
- def create_guild(self, name, region=None, icon=None):
+ async def create_guild(self, name, region=None, icon=None):
"""|coro|
Creates a :class:`Guild`.
@@ -903,13 +887,12 @@ class Client:
else:
region = region.value
- data = yield from self.http.create_guild(name, region, icon)
+ data = await self.http.create_guild(name, region, icon)
return Guild(data=data, state=self._connection)
# Invite management
- @asyncio.coroutine
- def get_invite(self, url):
+ async def get_invite(self, url):
"""|coro|
Gets an :class:`Invite` from a discord.gg URL or ID.
@@ -939,11 +922,10 @@ class Client:
"""
invite_id = self._resolve_invite(url)
- data = yield from self.http.get_invite(invite_id)
+ data = await self.http.get_invite(invite_id)
return Invite.from_incomplete(state=self._connection, data=data)
- @asyncio.coroutine
- def delete_invite(self, invite):
+ async def delete_invite(self, invite):
"""|coro|
Revokes an :class:`Invite`, URL, or ID to an invite.
@@ -967,12 +949,11 @@ class Client:
"""
invite_id = self._resolve_invite(invite)
- yield from self.http.delete_invite(invite_id)
+ await self.http.delete_invite(invite_id)
# Miscellaneous stuff
- @asyncio.coroutine
- def application_info(self):
+ async def application_info(self):
"""|coro|
Retrieve's the bot's application information.
@@ -987,13 +968,12 @@ class Client:
HTTPException
Retrieving the information failed somehow.
"""
- data = yield from self.http.application_info()
+ data = await self.http.application_info()
return AppInfo(id=int(data['id']), name=data['name'],
description=data['description'], icon=data['icon'],
owner=User(state=self._connection, data=data['owner']))
- @asyncio.coroutine
- def get_user_info(self, user_id):
+ async def get_user_info(self, user_id):
"""|coro|
Retrieves a :class:`User` based on their ID. This can only
@@ -1018,11 +998,10 @@ class Client:
HTTPException
Fetching the user failed.
"""
- data = yield from self.http.get_user_info(user_id)
+ data = await self.http.get_user_info(user_id)
return User(state=self._connection, data=data)
- @asyncio.coroutine
- def get_user_profile(self, user_id):
+ async def get_user_profile(self, user_id):
"""|coro|
Gets an arbitrary user's profile. This can only be used by non-bot accounts.
@@ -1046,7 +1025,7 @@ class Client:
"""
state = self._connection
- data = yield from self.http.get_user_profile(user_id)
+ data = await self.http.get_user_profile(user_id)
def transform(d):
return state._get_guild(int(d['id']))
@@ -1060,8 +1039,7 @@ class Client:
user=User(data=user, state=state),
connected_accounts=data['connected_accounts'])
- @asyncio.coroutine
- def get_webhook_info(self, webhook_id):
+ async def get_webhook_info(self, webhook_id):
"""|coro|
Retrieves a :class:`Webhook` with the specified ID.
@@ -1080,5 +1058,5 @@ class Client:
:class:`Webhook`
The webhook you requested.
"""
- data = yield from self.http.get_webhook(webhook_id)
+ data = await self.http.get_webhook(webhook_id)
return Webhook.from_state(data, state=self._connection)