Change order of documentation by source declaration.
This commit is contained in:
parent
93e3c360a7
commit
af94179be5
@ -411,7 +411,184 @@ class Client:
|
|||||||
log.info('sending reconnection frame to websocket {}'.format(payload))
|
log.info('sending reconnection frame to websocket {}'.format(payload))
|
||||||
yield from self.ws.send(utils.to_json(payload))
|
yield from self.ws.send(utils.to_json(payload))
|
||||||
|
|
||||||
# properties
|
# login state management
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def login(self, email, password):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Logs in the client with the specified credentials.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
email : str
|
||||||
|
The email used to login.
|
||||||
|
password : str
|
||||||
|
The password used to login.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
LoginFailure
|
||||||
|
The wrong credentials are passed.
|
||||||
|
HTTPException
|
||||||
|
An unknown HTTP related error occurred,
|
||||||
|
usually when it isn't 200 or the known incorrect credentials
|
||||||
|
passing status code.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# attempt to read the token from cache
|
||||||
|
if self.cache_auth:
|
||||||
|
yield from self._login_via_cache(email, password)
|
||||||
|
if self.is_logged_in:
|
||||||
|
return
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
'email': email,
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
|
||||||
|
data = utils.to_json(payload)
|
||||||
|
resp = yield from aiohttp.post(endpoints.LOGIN, data=data, headers=self.headers, loop=self.loop)
|
||||||
|
log.debug(request_logging_format.format(method='POST', response=resp))
|
||||||
|
if resp.status != 200:
|
||||||
|
yield from resp.release()
|
||||||
|
if resp.status == 400:
|
||||||
|
raise LoginFailure('Improper credentials have been passed.')
|
||||||
|
else:
|
||||||
|
raise HTTPException(resp, None)
|
||||||
|
|
||||||
|
log.info('logging in returned status code {}'.format(resp.status))
|
||||||
|
self.email = email
|
||||||
|
|
||||||
|
body = yield from resp.json()
|
||||||
|
self.token = body['token']
|
||||||
|
self.headers['authorization'] = self.token
|
||||||
|
self._is_logged_in.set()
|
||||||
|
|
||||||
|
# since we went through all this trouble
|
||||||
|
# let's make sure we don't have to do it again
|
||||||
|
if self.cache_auth:
|
||||||
|
self._update_cache(email, password)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def logout(self):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Logs out of Discord and closes all connections."""
|
||||||
|
response = yield from aiohttp.post(endpoints.LOGOUT, headers=self.headers, loop=self.loop)
|
||||||
|
yield from response.release()
|
||||||
|
yield from self.close()
|
||||||
|
self._is_logged_in.clear()
|
||||||
|
log.debug(request_logging_format.format(method='POST', response=response))
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def connect(self):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Creates a websocket connection and connects to the websocket listen
|
||||||
|
to messages from discord.
|
||||||
|
|
||||||
|
This function is implemented using a while loop in the background.
|
||||||
|
If you need to run this event listening in another thread then
|
||||||
|
you should run it in an executor or schedule the coroutine to
|
||||||
|
be executed later using ``loop.create_task``.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
-------
|
||||||
|
ClientException
|
||||||
|
If this is called before :meth:`login` was invoked successfully
|
||||||
|
or when an unexpected closure of the websocket occurs.
|
||||||
|
GatewayNotFound
|
||||||
|
If the gateway to connect to discord is not found. Usually if this
|
||||||
|
is thrown then there is a discord API outage.
|
||||||
|
"""
|
||||||
|
self.gateway = yield from self._get_gateway()
|
||||||
|
yield from self._make_websocket()
|
||||||
|
|
||||||
|
while not self.is_closed:
|
||||||
|
msg = yield from self.ws.recv()
|
||||||
|
if msg is None:
|
||||||
|
if self.ws.close_code == 1012:
|
||||||
|
yield from self.redirect_websocket(self.gateway)
|
||||||
|
continue
|
||||||
|
elif not self._is_ready.is_set():
|
||||||
|
raise ClientException('Unexpected websocket closure received')
|
||||||
|
else:
|
||||||
|
yield from self.close()
|
||||||
|
break
|
||||||
|
|
||||||
|
yield from self.received_message(msg)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def close(self):
|
||||||
|
"""Closes the websocket connection.
|
||||||
|
|
||||||
|
To reconnect the websocket connection, :meth:`connect` must be used.
|
||||||
|
"""
|
||||||
|
if self.is_closed:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.is_voice_connected():
|
||||||
|
yield from self.voice.disconnect()
|
||||||
|
self.voice = None
|
||||||
|
|
||||||
|
if self.ws.open:
|
||||||
|
yield from self.ws.close()
|
||||||
|
|
||||||
|
self.keep_alive.cancel()
|
||||||
|
self._closed.set()
|
||||||
|
self._is_ready.clear()
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def start(self, email, password):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
A shorthand coroutine for :meth:`login` + :meth:`connect`.
|
||||||
|
"""
|
||||||
|
yield from self.login(email, password)
|
||||||
|
yield from self.connect()
|
||||||
|
|
||||||
|
def run(self, email, password):
|
||||||
|
"""A blocking call that abstracts away the `event loop`_
|
||||||
|
initialisation from you.
|
||||||
|
|
||||||
|
If you want more control over the event loop then this
|
||||||
|
function should not be used. Use :meth:`start` coroutine
|
||||||
|
or :meth:`connect` + :meth:`login`.
|
||||||
|
|
||||||
|
Roughly Equivalent to: ::
|
||||||
|
|
||||||
|
try:
|
||||||
|
loop.run_until_complete(start(email, password))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
loop.run_until_complete(logout())
|
||||||
|
# cancel all tasks lingering
|
||||||
|
finally:
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
Warning
|
||||||
|
--------
|
||||||
|
This function must be the last function to call due to the fact that it
|
||||||
|
is blocking. That means that registration of events or anything being
|
||||||
|
called after this function call will not execute until it returns.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.loop.run_until_complete(self.start(email, password))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
self.loop.run_until_complete(self.logout())
|
||||||
|
pending = asyncio.Task.all_tasks()
|
||||||
|
gathered = asyncio.gather(*pending)
|
||||||
|
try:
|
||||||
|
gathered.cancel()
|
||||||
|
self.loop.run_forever()
|
||||||
|
gathered.exception()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
self.loop.close()
|
||||||
|
|
||||||
|
# properties
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_logged_in(self):
|
def is_logged_in(self):
|
||||||
@ -605,183 +782,6 @@ class Client:
|
|||||||
message = None
|
message = None
|
||||||
return message
|
return message
|
||||||
|
|
||||||
# login state management
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def login(self, email, password):
|
|
||||||
"""|coro|
|
|
||||||
|
|
||||||
Logs in the client with the specified credentials.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
email : str
|
|
||||||
The email used to login.
|
|
||||||
password : str
|
|
||||||
The password used to login.
|
|
||||||
|
|
||||||
Raises
|
|
||||||
------
|
|
||||||
LoginFailure
|
|
||||||
The wrong credentials are passed.
|
|
||||||
HTTPException
|
|
||||||
An unknown HTTP related error occurred,
|
|
||||||
usually when it isn't 200 or the known incorrect credentials
|
|
||||||
passing status code.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# attempt to read the token from cache
|
|
||||||
if self.cache_auth:
|
|
||||||
yield from self._login_via_cache(email, password)
|
|
||||||
if self.is_logged_in:
|
|
||||||
return
|
|
||||||
|
|
||||||
payload = {
|
|
||||||
'email': email,
|
|
||||||
'password': password
|
|
||||||
}
|
|
||||||
|
|
||||||
data = utils.to_json(payload)
|
|
||||||
resp = yield from aiohttp.post(endpoints.LOGIN, data=data, headers=self.headers, loop=self.loop)
|
|
||||||
log.debug(request_logging_format.format(method='POST', response=resp))
|
|
||||||
if resp.status != 200:
|
|
||||||
yield from resp.release()
|
|
||||||
if resp.status == 400:
|
|
||||||
raise LoginFailure('Improper credentials have been passed.')
|
|
||||||
else:
|
|
||||||
raise HTTPException(resp, None)
|
|
||||||
|
|
||||||
log.info('logging in returned status code {}'.format(resp.status))
|
|
||||||
self.email = email
|
|
||||||
|
|
||||||
body = yield from resp.json()
|
|
||||||
self.token = body['token']
|
|
||||||
self.headers['authorization'] = self.token
|
|
||||||
self._is_logged_in.set()
|
|
||||||
|
|
||||||
# since we went through all this trouble
|
|
||||||
# let's make sure we don't have to do it again
|
|
||||||
if self.cache_auth:
|
|
||||||
self._update_cache(email, password)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def logout(self):
|
|
||||||
"""|coro|
|
|
||||||
|
|
||||||
Logs out of Discord and closes all connections."""
|
|
||||||
response = yield from aiohttp.post(endpoints.LOGOUT, headers=self.headers, loop=self.loop)
|
|
||||||
yield from response.release()
|
|
||||||
yield from self.close()
|
|
||||||
self._is_logged_in.clear()
|
|
||||||
log.debug(request_logging_format.format(method='POST', response=response))
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def connect(self):
|
|
||||||
"""|coro|
|
|
||||||
|
|
||||||
Creates a websocket connection and connects to the websocket listen
|
|
||||||
to messages from discord.
|
|
||||||
|
|
||||||
This function is implemented using a while loop in the background.
|
|
||||||
If you need to run this event listening in another thread then
|
|
||||||
you should run it in an executor or schedule the coroutine to
|
|
||||||
be executed later using ``loop.create_task``.
|
|
||||||
|
|
||||||
Raises
|
|
||||||
-------
|
|
||||||
ClientException
|
|
||||||
If this is called before :meth:`login` was invoked successfully
|
|
||||||
or when an unexpected closure of the websocket occurs.
|
|
||||||
GatewayNotFound
|
|
||||||
If the gateway to connect to discord is not found. Usually if this
|
|
||||||
is thrown then there is a discord API outage.
|
|
||||||
"""
|
|
||||||
self.gateway = yield from self._get_gateway()
|
|
||||||
yield from self._make_websocket()
|
|
||||||
|
|
||||||
while not self.is_closed:
|
|
||||||
msg = yield from self.ws.recv()
|
|
||||||
if msg is None:
|
|
||||||
if self.ws.close_code == 1012:
|
|
||||||
yield from self.redirect_websocket(self.gateway)
|
|
||||||
continue
|
|
||||||
elif not self._is_ready.is_set():
|
|
||||||
raise ClientException('Unexpected websocket closure received')
|
|
||||||
else:
|
|
||||||
yield from self.close()
|
|
||||||
break
|
|
||||||
|
|
||||||
yield from self.received_message(msg)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def close(self):
|
|
||||||
"""Closes the websocket connection.
|
|
||||||
|
|
||||||
To reconnect the websocket connection, :meth:`connect` must be used.
|
|
||||||
"""
|
|
||||||
if self.is_closed:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.is_voice_connected():
|
|
||||||
yield from self.voice.disconnect()
|
|
||||||
self.voice = None
|
|
||||||
|
|
||||||
if self.ws.open:
|
|
||||||
yield from self.ws.close()
|
|
||||||
|
|
||||||
self.keep_alive.cancel()
|
|
||||||
self._closed.set()
|
|
||||||
self._is_ready.clear()
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def start(self, email, password):
|
|
||||||
"""|coro|
|
|
||||||
|
|
||||||
A shorthand coroutine for :meth:`login` + :meth:`connect`.
|
|
||||||
"""
|
|
||||||
yield from self.login(email, password)
|
|
||||||
yield from self.connect()
|
|
||||||
|
|
||||||
def run(self, email, password):
|
|
||||||
"""A blocking call that abstracts away the `event loop`_
|
|
||||||
initialisation from you.
|
|
||||||
|
|
||||||
If you want more control over the event loop then this
|
|
||||||
function should not be used. Use :meth:`start` coroutine
|
|
||||||
or :meth:`connect` + :meth:`login`.
|
|
||||||
|
|
||||||
Roughly Equivalent to: ::
|
|
||||||
|
|
||||||
try:
|
|
||||||
loop.run_until_complete(start(email, password))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
loop.run_until_complete(logout())
|
|
||||||
# cancel all tasks lingering
|
|
||||||
finally:
|
|
||||||
loop.close()
|
|
||||||
|
|
||||||
Warning
|
|
||||||
--------
|
|
||||||
This function must be the last function to call due to the fact that it
|
|
||||||
is blocking. That means that registration of events or anything being
|
|
||||||
called after this function call will not execute until it returns.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.loop.run_until_complete(self.start(email, password))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.loop.run_until_complete(self.logout())
|
|
||||||
pending = asyncio.Task.all_tasks()
|
|
||||||
gathered = asyncio.gather(*pending)
|
|
||||||
try:
|
|
||||||
gathered.cancel()
|
|
||||||
self.loop.run_forever()
|
|
||||||
gathered.exception()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
self.loop.close()
|
|
||||||
|
|
||||||
# event registration
|
# event registration
|
||||||
|
|
||||||
def event(self, coro):
|
def event(self, coro):
|
||||||
|
@ -35,6 +35,8 @@ extensions = [
|
|||||||
'sphinx.ext.napoleon',
|
'sphinx.ext.napoleon',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
autodoc_member_order = 'bysource'
|
||||||
|
|
||||||
extlinks = {
|
extlinks = {
|
||||||
'issue': ('https://github.com/Rapptz/discord.py/issues/%s', 'issue '),
|
'issue': ('https://github.com/Rapptz/discord.py/issues/%s', 'issue '),
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user