mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-06-05 11:27:13 +00:00
parent
a42bebe581
commit
7ed26db3b3
@ -49,7 +49,7 @@ from . import utils, opus, abc
|
|||||||
from .enums import *
|
from .enums import *
|
||||||
from .embeds import Embed
|
from .embeds import Embed
|
||||||
from .mentions import AllowedMentions
|
from .mentions import AllowedMentions
|
||||||
from .shard import AutoShardedClient
|
from .shard import AutoShardedClient, ShardInfo
|
||||||
from .player import *
|
from .player import *
|
||||||
from .webhook import *
|
from .webhook import *
|
||||||
from .voice_client import VoiceClient
|
from .voice_client import VoiceClient
|
||||||
|
104
discord/shard.py
104
discord/shard.py
@ -103,6 +103,10 @@ class Shard:
|
|||||||
self._cancel_task()
|
self._cancel_task()
|
||||||
await self.ws.close(code=1000)
|
await self.ws.close(code=1000)
|
||||||
|
|
||||||
|
async def disconnect(self):
|
||||||
|
await self.close()
|
||||||
|
self._dispatch('shard_disconnect', self.id)
|
||||||
|
|
||||||
async def _handle_disconnect(self, e):
|
async def _handle_disconnect(self, e):
|
||||||
self._dispatch('disconnect')
|
self._dispatch('disconnect')
|
||||||
self._dispatch('shard_disconnect', self.id)
|
self._dispatch('shard_disconnect', self.id)
|
||||||
@ -178,6 +182,70 @@ class Shard:
|
|||||||
else:
|
else:
|
||||||
self.launch()
|
self.launch()
|
||||||
|
|
||||||
|
class ShardInfo:
|
||||||
|
"""A class that gives information and control over a specific shard.
|
||||||
|
|
||||||
|
You can retrieve this object via :meth:`AutoShardedClient.get_shard`
|
||||||
|
or :attr:`AutoShardedClient.shards`.
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
------------
|
||||||
|
id: :class:`int`
|
||||||
|
The shard ID for this shard.
|
||||||
|
shard_count: Optional[:class:`int`]
|
||||||
|
The shard count for this cluster. If this is ``None`` then the bot has not started yet.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ('_parent', 'id', 'shard_count')
|
||||||
|
|
||||||
|
def __init__(self, parent, shard_count):
|
||||||
|
self._parent = parent
|
||||||
|
self.id = parent.id
|
||||||
|
self.shard_count = shard_count
|
||||||
|
|
||||||
|
def is_closed(self):
|
||||||
|
""":class:`bool`: Whether the shard connection is currently closed."""
|
||||||
|
return not self._parent.ws.open
|
||||||
|
|
||||||
|
async def disconnect(self):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Disconnects a shard. When this is called, the shard connection will no
|
||||||
|
longer be open.
|
||||||
|
|
||||||
|
If the shard is already disconnected this does nothing.
|
||||||
|
"""
|
||||||
|
if self.is_closed():
|
||||||
|
return
|
||||||
|
|
||||||
|
await self._parent.disconnect()
|
||||||
|
|
||||||
|
async def reconnect(self):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Disconnects and then connects the shard again.
|
||||||
|
"""
|
||||||
|
if not self.is_closed():
|
||||||
|
await self._parent.disconnect()
|
||||||
|
await self._parent.reconnect()
|
||||||
|
|
||||||
|
async def connect(self):
|
||||||
|
"""|coro|
|
||||||
|
|
||||||
|
Connects a shard. If the shard is already connected this does nothing.
|
||||||
|
"""
|
||||||
|
if not self.is_closed():
|
||||||
|
return
|
||||||
|
|
||||||
|
await self._parent.reconnect()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def latency(self):
|
||||||
|
""":class:`float`: Measures latency between a HEARTBEAT and a HEARTBEAT_ACK in seconds for this shard."""
|
||||||
|
return self._parent.ws.latency
|
||||||
|
|
||||||
class AutoShardedClient(Client):
|
class AutoShardedClient(Client):
|
||||||
"""A client similar to :class:`Client` except it handles the complications
|
"""A client similar to :class:`Client` except it handles the complications
|
||||||
of sharding for the user into a more manageable and transparent single
|
of sharding for the user into a more manageable and transparent single
|
||||||
@ -221,14 +289,14 @@ class AutoShardedClient(Client):
|
|||||||
|
|
||||||
# instead of a single websocket, we have multiple
|
# instead of a single websocket, we have multiple
|
||||||
# the key is the shard_id
|
# the key is the shard_id
|
||||||
self.shards = {}
|
self.__shards = {}
|
||||||
self._connection._get_websocket = self._get_websocket
|
self._connection._get_websocket = self._get_websocket
|
||||||
self._queue = asyncio.PriorityQueue()
|
self.__queue = asyncio.PriorityQueue()
|
||||||
|
|
||||||
def _get_websocket(self, guild_id=None, *, shard_id=None):
|
def _get_websocket(self, guild_id=None, *, shard_id=None):
|
||||||
if shard_id is None:
|
if shard_id is None:
|
||||||
shard_id = (guild_id >> 22) % self.shard_count
|
shard_id = (guild_id >> 22) % self.shard_count
|
||||||
return self.shards[shard_id].ws
|
return self.__shards[shard_id].ws
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def latency(self):
|
def latency(self):
|
||||||
@ -238,9 +306,9 @@ class AutoShardedClient(Client):
|
|||||||
latency of every shard's latency. To get a list of shard latency, check the
|
latency of every shard's latency. To get a list of shard latency, check the
|
||||||
:attr:`latencies` property. Returns ``nan`` if there are no shards ready.
|
:attr:`latencies` property. Returns ``nan`` if there are no shards ready.
|
||||||
"""
|
"""
|
||||||
if not self.shards:
|
if not self.__shards:
|
||||||
return float('nan')
|
return float('nan')
|
||||||
return sum(latency for _, latency in self.latencies) / len(self.shards)
|
return sum(latency for _, latency in self.latencies) / len(self.__shards)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def latencies(self):
|
def latencies(self):
|
||||||
@ -248,7 +316,21 @@ class AutoShardedClient(Client):
|
|||||||
|
|
||||||
This returns a list of tuples with elements ``(shard_id, latency)``.
|
This returns a list of tuples with elements ``(shard_id, latency)``.
|
||||||
"""
|
"""
|
||||||
return [(shard_id, shard.ws.latency) for shard_id, shard in self.shards.items()]
|
return [(shard_id, shard.ws.latency) for shard_id, shard in self.__shards.items()]
|
||||||
|
|
||||||
|
def get_shard(self, shard_id):
|
||||||
|
"""Optional[:class:`ShardInfo`]: Gets the shard information at a given shard ID or ``None`` if not found."""
|
||||||
|
try:
|
||||||
|
parent = self.__shards[shard_id]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return ShardInfo(parent, self.shard_count)
|
||||||
|
|
||||||
|
@utils.cached_property
|
||||||
|
def shards(self):
|
||||||
|
"""Mapping[int, :class:`ShardInfo`]: Returns a mapping of shard IDs to their respective info object."""
|
||||||
|
return { shard_id: ShardInfo(parent, self.shard_count) for shard_id, parent in self.__shards.items() }
|
||||||
|
|
||||||
async def request_offline_members(self, *guilds):
|
async def request_offline_members(self, *guilds):
|
||||||
r"""|coro|
|
r"""|coro|
|
||||||
@ -291,7 +373,7 @@ class AutoShardedClient(Client):
|
|||||||
return await self.launch_shard(gateway, shard_id)
|
return await self.launch_shard(gateway, shard_id)
|
||||||
|
|
||||||
# keep reading the shard while others connect
|
# keep reading the shard while others connect
|
||||||
self.shards[shard_id] = ret = Shard(ws, self)
|
self.__shards[shard_id] = ret = Shard(ws, self)
|
||||||
ret.launch()
|
ret.launch()
|
||||||
|
|
||||||
async def launch_shards(self):
|
async def launch_shards(self):
|
||||||
@ -316,7 +398,7 @@ class AutoShardedClient(Client):
|
|||||||
await self.launch_shards()
|
await self.launch_shards()
|
||||||
|
|
||||||
while not self.is_closed():
|
while not self.is_closed():
|
||||||
item = await self._queue.get()
|
item = await self.__queue.get()
|
||||||
if item.type == EventType.close:
|
if item.type == EventType.close:
|
||||||
await self.close()
|
await self.close()
|
||||||
if isinstance(item.error, ConnectionClosed) and item.error.code != 1000:
|
if isinstance(item.error, ConnectionClosed) and item.error.code != 1000:
|
||||||
@ -346,7 +428,7 @@ class AutoShardedClient(Client):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
to_close = [asyncio.ensure_future(shard.close(), loop=self.loop) for shard in self.shards.values()]
|
to_close = [asyncio.ensure_future(shard.close(), loop=self.loop) for shard in self.__shards.values()]
|
||||||
if to_close:
|
if to_close:
|
||||||
await asyncio.wait(to_close)
|
await asyncio.wait(to_close)
|
||||||
|
|
||||||
@ -395,12 +477,12 @@ class AutoShardedClient(Client):
|
|||||||
status = str(status)
|
status = str(status)
|
||||||
|
|
||||||
if shard_id is None:
|
if shard_id is None:
|
||||||
for shard in self.shards.values():
|
for shard in self.__shards.values():
|
||||||
await shard.ws.change_presence(activity=activity, status=status, afk=afk)
|
await shard.ws.change_presence(activity=activity, status=status, afk=afk)
|
||||||
|
|
||||||
guilds = self._connection.guilds
|
guilds = self._connection.guilds
|
||||||
else:
|
else:
|
||||||
shard = self.shards[shard_id]
|
shard = self.__shards[shard_id]
|
||||||
await shard.ws.change_presence(activity=activity, status=status, afk=afk)
|
await shard.ws.change_presence(activity=activity, status=status, afk=afk)
|
||||||
guilds = [g for g in self._connection.guilds if g.shard_id == shard_id]
|
guilds = [g for g in self._connection.guilds if g.shard_id == shard_id]
|
||||||
|
|
||||||
|
14
docs/api.rst
14
docs/api.rst
@ -2756,7 +2756,7 @@ Data Classes
|
|||||||
Some classes are just there to be data containers, this lists them.
|
Some classes are just there to be data containers, this lists them.
|
||||||
|
|
||||||
Unlike :ref:`models <discord_api_models>` you are allowed to create
|
Unlike :ref:`models <discord_api_models>` you are allowed to create
|
||||||
these yourself, even if they can also be used to hold attributes.
|
most of these yourself, even if they can also be used to hold attributes.
|
||||||
|
|
||||||
Nearly all classes here have :ref:`py:slots` defined which means that it is
|
Nearly all classes here have :ref:`py:slots` defined which means that it is
|
||||||
impossible to have dynamic attributes to the data classes.
|
impossible to have dynamic attributes to the data classes.
|
||||||
@ -2837,22 +2837,28 @@ PermissionOverwrite
|
|||||||
.. autoclass:: PermissionOverwrite
|
.. autoclass:: PermissionOverwrite
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
ShardInfo
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: ShardInfo()
|
||||||
|
:members:
|
||||||
|
|
||||||
SystemChannelFlags
|
SystemChannelFlags
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: SystemChannelFlags
|
.. autoclass:: SystemChannelFlags()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
MessageFlags
|
MessageFlags
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: MessageFlags
|
.. autoclass:: MessageFlags()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
PublicUserFlags
|
PublicUserFlags
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: PublicUserFlags
|
.. autoclass:: PublicUserFlags()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user