aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2019-12-20 23:10:46 -0500
committerRapptz <[email protected]>2020-09-23 03:21:15 -0400
commita6381dcf77f773316ea59767a06d06cfcc57e4d9 (patch)
tree91e3606099ec7329518f5e9648a784bc3da83e73
parentProperly handle disconnects in voice when force disconnected (diff)
downloaddiscord.py-a6381dcf77f773316ea59767a06d06cfcc57e4d9.tar.xz
discord.py-a6381dcf77f773316ea59767a06d06cfcc57e4d9.zip
Add support for guild intents
-rw-r--r--discord/client.py4
-rw-r--r--discord/flags.py317
-rw-r--r--discord/gateway.py3
-rw-r--r--discord/state.py8
4 files changed, 331 insertions, 1 deletions
diff --git a/discord/client.py b/discord/client.py
index 407fd47f..91d83da4 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -140,6 +140,10 @@ class Client:
Integer starting at ``0`` and less than :attr:`.shard_count`.
shard_count: Optional[:class:`int`]
The total number of shards.
+ intents: :class:`Intents`
+ A list of intents that you want to enable for the session. This is a way of
+ disabling and enabling certain gateway events from triggering and being sent.
+ Currently, if no intents are passed then you will receive all data.
fetch_offline_members: :class:`bool`
Indicates if :func:`.on_ready` should be delayed to fetch all offline
members from the guilds the client belongs to. If this is ``False``\, then
diff --git a/discord/flags.py b/discord/flags.py
index 448bced2..4f5f197e 100644
--- a/discord/flags.py
+++ b/discord/flags.py
@@ -29,7 +29,8 @@ from .enums import UserFlags
__all__ = (
'SystemChannelFlags',
'MessageFlags',
- 'PublicUserFlags'
+ 'PublicUserFlags',
+ 'Intents',
)
class flag_value:
@@ -327,3 +328,317 @@ class PublicUserFlags(BaseFlags):
def all(self):
"""List[:class:`UserFlags`]: Returns all public flags the user has."""
return [public_flag for public_flag in UserFlags if self._has_flag(public_flag.value)]
+
+
+@fill_with_flags()
+class Intents(BaseFlags):
+ r"""Wraps up a Discord gateway intent flag.
+
+ Similar to :class:`Permissions`\, the properties provided are two way.
+ You can set and retrieve individual bits using the properties as if they
+ were regular bools.
+
+ To construct an object you can pass keyword arguments denoting the flags
+ to enable or disable.
+
+ This is used to disable certain gateway features that are unnecessary to
+ run your bot. To make use of this, it is passed to the ``intents`` keyword
+ argument of :class:`Client`.
+
+ A default instance of this class has everything enabled except :attr:`presences`.
+
+ .. container:: operations
+
+ .. describe:: x == y
+
+ Checks if two flags are equal.
+ .. describe:: x != y
+
+ Checks if two flags are not equal.
+ .. describe:: hash(x)
+
+ Return the flag's hash.
+ .. describe:: iter(x)
+
+ Returns an iterator of ``(name, value)`` pairs. This allows it
+ to be, for example, constructed as a dict or a list of pairs.
+
+ Attributes
+ -----------
+ value: :class:`int`
+ The raw value. You should query flags via the properties
+ rather than using this raw value.
+ """
+
+ __slots__ = ()
+
+ def __init__(self, **kwargs):
+ # Change the default value to everything being enabled
+ # except presences
+ bits = max(self.VALID_FLAGS.values()).bit_length()
+ self.value = (1 << bits) - 1
+ self.presences = False
+ for key, value in kwargs.items():
+ if key not in self.VALID_FLAGS:
+ raise TypeError('%r is not a valid flag name.' % key)
+ setattr(self, key, value)
+
+ @classmethod
+ def all(cls):
+ """A factory method that creates a :class:`Intents` with everything enabled."""
+ bits = max(cls.VALID_FLAGS.values()).bit_length()
+ value = (1 << bits) - 1
+ self = cls.__new__(cls)
+ self.value = value
+ return self
+
+ @classmethod
+ def none(cls):
+ """A factory method that creates a :class:`Intents` with everything disabled."""
+ self = cls.__new__(cls)
+ self.value = self.DEFAULT_VALUE
+ return self
+
+ @flag_value
+ def guilds(self):
+ """:class:`bool`: Whether guild related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_guild_join`
+ - :func:`on_guild_remove`
+ - :func:`on_guild_available`
+ - :func:`on_guild_unavailable`
+ - :func:`on_guild_channel_update`
+ - :func:`on_guild_channel_create`
+ - :func:`on_guild_channel_delete`
+ - :func:`on_guild_channel_pins_update`
+ """
+ return 1 << 0
+
+ @flag_value
+ def members(self):
+ """:class:`bool`: Whether guild member related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_member_join`
+ - :func:`on_member_remove`
+ - :func:`on_member_update` (nickname, roles)
+ """
+ return 1 << 1
+
+ @flag_value
+ def bans(self):
+ """:class:`bool`: Whether guild ban related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_member_ban`
+ - :func:`on_member_unban`
+ """
+ return 1 << 2
+
+ @flag_value
+ def emojis(self):
+ """:class:`bool`: Whether guild emoji related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_guild_emojis_update`
+ """
+ return 1 << 3
+
+ @flag_value
+ def integrations(self):
+ """:class:`bool`: Whether guild integration related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_guild_integrations_update`
+ """
+ return 1 << 4
+
+ @flag_value
+ def webhooks(self):
+ """:class:`bool`: Whether guild webhook related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_webhooks_update`
+ """
+ return 1 << 5
+
+ @flag_value
+ def invites(self):
+ """:class:`bool`: Whether guild invite related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_invite_create`
+ - :func:`on_invite_delete`
+ """
+ return 1 << 6
+
+ @flag_value
+ def voice_states(self):
+ """:class:`bool`: Whether guild voice state related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_voice_state_update`
+ """
+ return 1 << 7
+
+ @flag_value
+ def presences(self):
+ """:class:`bool`: Whether guild voice state related events are enabled.
+
+ This corresponds to the following events:
+
+ - :func:`on_member_update` (activities, status)
+ - :func:`on_user_update`
+
+ .. note::
+
+ Currently, this requires opting in explicitly via the dev portal as well.
+ Bots in over 100 guilds will need to apply to Discord for approval.
+ """
+ return 1 << 8
+
+ @flag_value
+ def messages(self):
+ """:class:`bool`: Whether guild and direct message related events are enabled.
+
+ This is a shortcut to set or get both :attr:`guild_messages` and :attr:`dm_messages`.
+
+ This corresponds to the following events:
+
+ - :func:`on_message` (both guilds and DMs)
+ - :func:`on_message_update` (both guilds and DMs)
+ - :func:`on_message_delete` (both guilds and DMs)
+ - :func:`on_raw_message_delete` (both guilds and DMs)
+ - :func:`on_raw_message_update` (both guilds and DMs)
+ - :func:`on_private_channel_create`
+ """
+ return (1 << 9) | (1 << 12)
+
+ @flag_value
+ def guild_messages(self):
+ """:class:`bool`: Whether guild message related events are enabled.
+
+ See also :attr:`dm_messages` for DMs or :attr:`messages` for both.
+
+ This corresponds to the following events:
+
+ - :func:`on_message` (only for guilds)
+ - :func:`on_message_update` (only for guilds)
+ - :func:`on_message_delete` (only for guilds)
+ - :func:`on_raw_message_delete` (only for guilds)
+ - :func:`on_raw_message_update` (only for guilds)
+ """
+ return 1 << 9
+
+ @flag_value
+ def dm_messages(self):
+ """:class:`bool`: Whether direct message related events are enabled.
+
+ See also :attr:`guild_messages` for guilds or :attr:`messages` for both.
+
+ This corresponds to the following events:
+
+ - :func:`on_message` (only for DMs)
+ - :func:`on_message_update` (only for DMs)
+ - :func:`on_message_delete` (only for DMs)
+ - :func:`on_raw_message_delete` (only for DMs)
+ - :func:`on_raw_message_update` (only for DMs)
+ - :func:`on_private_channel_create`
+ """
+ return 1 << 12
+
+ @flag_value
+ def reactions(self):
+ """:class:`bool`: Whether guild and direct message reaction related events are enabled.
+
+ This is a shortcut to set or get both :attr:`guild_reactions` and :attr:`dm_reactions`.
+
+ This corresponds to the following events:
+
+ - :func:`on_reaction_add` (both guilds and DMs)
+ - :func:`on_reaction_remove` (both guilds and DMs)
+ - :func:`on_reaction_clear` (both guilds and DMs)
+ - :func:`on_raw_reaction_add` (both guilds and DMs)
+ - :func:`on_raw_reaction_remove` (both guilds and DMs)
+ - :func:`on_raw_reaction_clear` (both guilds and DMs)
+ """
+ return (1 << 10) | (1 << 13)
+
+ @flag_value
+ def guild_reactions(self):
+ """:class:`bool`: Whether guild message reaction related events are enabled.
+
+ See also :attr:`dm_reactions` for DMs or :attr:`reactions` for both.
+
+ This corresponds to the following events:
+
+ - :func:`on_reaction_add` (only for guilds)
+ - :func:`on_reaction_remove` (only for guilds)
+ - :func:`on_reaction_clear` (only for guilds)
+ - :func:`on_raw_reaction_add` (only for guilds)
+ - :func:`on_raw_reaction_remove` (only for guilds)
+ - :func:`on_raw_reaction_clear` (only for guilds)
+ """
+ return 1 << 10
+
+ @flag_value
+ def dm_reactions(self):
+ """:class:`bool`: Whether direct message reaction related events are enabled.
+
+ See also :attr:`guild_reactions` for guilds or :attr:`reactions` for both.
+
+ This corresponds to the following events:
+
+ - :func:`on_reaction_add` (only for DMs)
+ - :func:`on_reaction_remove` (only for DMs)
+ - :func:`on_reaction_clear` (only for DMs)
+ - :func:`on_raw_reaction_add` (only for DMs)
+ - :func:`on_raw_reaction_remove` (only for DMs)
+ - :func:`on_raw_reaction_clear` (only for DMs)
+ """
+ return 1 << 13
+
+ @flag_value
+ def typing(self):
+ """:class:`bool`: Whether guild and direct message typing related events are enabled.
+
+ This is a shortcut to set or get both :attr:`guild_typing` and :attr:`dm_typing`.
+
+ This corresponds to the following events:
+
+ - :func:`on_typing` (both guilds and DMs)
+ """
+ return (1 << 11) | (1 << 14)
+
+ @flag_value
+ def guild_typing(self):
+ """:class:`bool`: Whether guild and direct message typing related events are enabled.
+
+ See also :attr:`dm_typing` for DMs or :attr:`typing` for both.
+
+ This corresponds to the following events:
+
+ - :func:`on_typing` (only for guilds)
+ """
+ return 1 << 11
+
+ @flag_value
+ def dm_typing(self):
+ """:class:`bool`: Whether guild and direct message typing related events are enabled.
+
+ See also :attr:`guild_typing` for guilds or :attr:`typing` for both.
+
+ This corresponds to the following events:
+
+ - :func:`on_typing` (only for DMs)
+ """
+ return 1 << 14
diff --git a/discord/gateway.py b/discord/gateway.py
index 382d60f1..ab595566 100644
--- a/discord/gateway.py
+++ b/discord/gateway.py
@@ -343,6 +343,9 @@ class DiscordWebSocket:
'afk': False
}
+ if state._intents is not None:
+ payload['d']['intents'] = state._intents
+
await self.call_hooks('before_identify', self.shard_id, initial=self._initial_identify)
await self.send_as_json(payload)
log.info('Shard ID %s has sent the IDENTIFY payload.', self.shard_id)
diff --git a/discord/state.py b/discord/state.py
index fc297d03..6c0f1e89 100644
--- a/discord/state.py
+++ b/discord/state.py
@@ -51,6 +51,7 @@ from .member import Member
from .role import Role
from .enums import ChannelType, try_enum, Status, Enum
from . import utils
+from .flags import Intents
from .embeds import Embed
from .object import Object
from .invite import Invite
@@ -115,8 +116,15 @@ class ConnectionState:
else:
status = str(status)
+ intents = options.get('intents', None)
+ if intents is not None:
+ if not isinstance(intents, Intents):
+ raise TypeError('intents parameter must be Intent not %r' % type(intents))
+ intents = intents.value
+
self._activity = activity
self._status = status
+ self._intents = intents
self.parsers = parsers = {}
for attr, func in inspect.getmembers(self):