Allow finer grained control over the member cache.
This commit is contained in:
		@@ -141,9 +141,14 @@ class Client:
 | 
				
			|||||||
    shard_count: Optional[:class:`int`]
 | 
					    shard_count: Optional[:class:`int`]
 | 
				
			||||||
        The total number of shards.
 | 
					        The total number of shards.
 | 
				
			||||||
    intents: :class:`Intents`
 | 
					    intents: :class:`Intents`
 | 
				
			||||||
        A list of intents that you want to enable for the session. This is a way of
 | 
					        The 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.
 | 
					        disabling and enabling certain gateway events from triggering and being sent.
 | 
				
			||||||
        Currently, if no intents are passed then you will receive all data.
 | 
					
 | 
				
			||||||
 | 
					        .. versionadded:: 1.5
 | 
				
			||||||
 | 
					    member_cache_flags: :class:`MemberCacheFlags`
 | 
				
			||||||
 | 
					        Allows for finer control over how the library caches members.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .. versionadded:: 1.5
 | 
				
			||||||
    fetch_offline_members: :class:`bool`
 | 
					    fetch_offline_members: :class:`bool`
 | 
				
			||||||
        Indicates if :func:`.on_ready` should be delayed to fetch all offline
 | 
					        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
 | 
					        members from the guilds the client belongs to. If this is ``False``\, then
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,7 @@ __all__ = (
 | 
				
			|||||||
    'Theme',
 | 
					    'Theme',
 | 
				
			||||||
    'WebhookType',
 | 
					    'WebhookType',
 | 
				
			||||||
    'ExpireBehaviour',
 | 
					    'ExpireBehaviour',
 | 
				
			||||||
    'ExpireBehavior'
 | 
					    'ExpireBehavior',
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _create_value_cls(name):
 | 
					def _create_value_cls(name):
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										126
									
								
								discord/flags.py
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								discord/flags.py
									
									
									
									
									
								
							@@ -31,6 +31,7 @@ __all__ = (
 | 
				
			|||||||
    'MessageFlags',
 | 
					    'MessageFlags',
 | 
				
			||||||
    'PublicUserFlags',
 | 
					    'PublicUserFlags',
 | 
				
			||||||
    'Intents',
 | 
					    'Intents',
 | 
				
			||||||
 | 
					    'MemberCacheFlags',
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class flag_value:
 | 
					class flag_value:
 | 
				
			||||||
@@ -651,3 +652,128 @@ class Intents(BaseFlags):
 | 
				
			|||||||
        - :func:`on_typing` (only for DMs)
 | 
					        - :func:`on_typing` (only for DMs)
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return 1 << 14
 | 
					        return 1 << 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@fill_with_flags()
 | 
				
			||||||
 | 
					class MemberCacheFlags(BaseFlags):
 | 
				
			||||||
 | 
					    """Controls the library's cache policy when it comes to members.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This allows for finer grained control over what members are cached.
 | 
				
			||||||
 | 
					    For more information, check :attr:`Client.member_cache_flags`. Note
 | 
				
			||||||
 | 
					    that the bot's own member is always cached.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Due to a quirk in how Discord works, in order to ensure proper cleanup
 | 
				
			||||||
 | 
					    of cache resources it is recommended to have :attr:`Intents.members`
 | 
				
			||||||
 | 
					    enabled. Otherwise the library cannot know when a member leaves a guild and
 | 
				
			||||||
 | 
					    is thus unable to cleanup after itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    To construct an object you can pass keyword arguments denoting the flags
 | 
				
			||||||
 | 
					    to enable or disable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The default value is all flags enabled.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. versionadded:: 1.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. 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):
 | 
				
			||||||
 | 
					        bits = max(self.VALID_FLAGS.values()).bit_length()
 | 
				
			||||||
 | 
					        self.value = (1 << bits) - 1
 | 
				
			||||||
 | 
					        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:`MemberCacheFlags` 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:`MemberCacheFlags` with everything disabled."""
 | 
				
			||||||
 | 
					        self = cls.__new__(cls)
 | 
				
			||||||
 | 
					        self.value = self.DEFAULT_VALUE
 | 
				
			||||||
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @flag_value
 | 
				
			||||||
 | 
					    def online(self):
 | 
				
			||||||
 | 
					        """:class:`bool`: Whether to cache members with a status.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        For example, members that are part of the initial ``GUILD_CREATE``
 | 
				
			||||||
 | 
					        or become online at a later point. This requires :attr:`Intents.presences`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Members that go offline are no longer cached.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @flag_value
 | 
				
			||||||
 | 
					    def voice(self):
 | 
				
			||||||
 | 
					        """:class:`bool`: Whether to cache members that are in voice.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This requires :attr:`Intents.voice_states`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Members that leave voice are no longer cached.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @flag_value
 | 
				
			||||||
 | 
					    def joined(self):
 | 
				
			||||||
 | 
					        """:class:`bool`: Whether to cache members that joined the guild
 | 
				
			||||||
 | 
					        or are chunked as part of the initial log in flow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        This requires :attr:`Intents.members`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Members that leave the guild are no longer cached.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _verify_intents(self, intents):
 | 
				
			||||||
 | 
					        if self.online and not intents.presences:
 | 
				
			||||||
 | 
					            raise ValueError('MemberCacheFlags.online requires Intents.presences enabled')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.voice and not intents.voice_states:
 | 
				
			||||||
 | 
					            raise ValueError('MemberCacheFlags.voice requires Intents.voice_states')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.joined and not intents.members:
 | 
				
			||||||
 | 
					            raise ValueError('MemberCacheFlags.joined requires Intents.members')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not self.joined and self.voice and self.online:
 | 
				
			||||||
 | 
					            msg = 'MemberCacheFlags.voice and MemberCacheFlags.online require MemberCacheFlags.joined ' \
 | 
				
			||||||
 | 
					                  'to properly evict members from the cache.'
 | 
				
			||||||
 | 
					            raise ValueError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def _voice_only(self):
 | 
				
			||||||
 | 
					        return self.value == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def _online_only(self):
 | 
				
			||||||
 | 
					        return self.value == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -305,11 +305,12 @@ class Guild(Hashable):
 | 
				
			|||||||
        self._rules_channel_id = utils._get_as_snowflake(guild, 'rules_channel_id')
 | 
					        self._rules_channel_id = utils._get_as_snowflake(guild, 'rules_channel_id')
 | 
				
			||||||
        self._public_updates_channel_id = utils._get_as_snowflake(guild, 'public_updates_channel_id')
 | 
					        self._public_updates_channel_id = utils._get_as_snowflake(guild, 'public_updates_channel_id')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cache_members = self._state._cache_members
 | 
					        cache_online_members = self._state._member_cache_flags.online
 | 
				
			||||||
 | 
					        cache_joined = self._state._member_cache_flags.joined
 | 
				
			||||||
        self_id = self._state.self_id
 | 
					        self_id = self._state.self_id
 | 
				
			||||||
        for mdata in guild.get('members', []):
 | 
					        for mdata in guild.get('members', []):
 | 
				
			||||||
            member = Member(data=mdata, guild=self, state=state)
 | 
					            member = Member(data=mdata, guild=self, state=state)
 | 
				
			||||||
            if cache_members or member.id == self_id:
 | 
					            if cache_joined or (cache_online_members and member.raw_status != 'offline') or member.id == self_id:
 | 
				
			||||||
                self._add_member(member)
 | 
					                self._add_member(member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._sync(guild)
 | 
					        self._sync(guild)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -291,6 +291,14 @@ class Member(discord.abc.Messageable, _BaseUser):
 | 
				
			|||||||
        """:class:`Status`: The member's overall status. If the value is unknown, then it will be a :class:`str` instead."""
 | 
					        """:class:`Status`: The member's overall status. If the value is unknown, then it will be a :class:`str` instead."""
 | 
				
			||||||
        return try_enum(Status, self._client_status[None])
 | 
					        return try_enum(Status, self._client_status[None])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def raw_status(self):
 | 
				
			||||||
 | 
					        """:class:`str`: The member's overall status as a string value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .. versionadded:: 1.5
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._client_status[None]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @status.setter
 | 
					    @status.setter
 | 
				
			||||||
    def status(self, value):
 | 
					    def status(self, value):
 | 
				
			||||||
        # internal use only
 | 
					        # internal use only
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,7 @@ from .member import Member
 | 
				
			|||||||
from .role import Role
 | 
					from .role import Role
 | 
				
			||||||
from .enums import ChannelType, try_enum, Status
 | 
					from .enums import ChannelType, try_enum, Status
 | 
				
			||||||
from . import utils
 | 
					from . import utils
 | 
				
			||||||
from .flags import Intents
 | 
					from .flags import Intents, MemberCacheFlags
 | 
				
			||||||
from .embeds import Embed
 | 
					from .embeds import Embed
 | 
				
			||||||
from .object import Object
 | 
					from .object import Object
 | 
				
			||||||
from .invite import Invite
 | 
					from .invite import Invite
 | 
				
			||||||
@@ -116,8 +116,6 @@ class ConnectionState:
 | 
				
			|||||||
            raise TypeError('allowed_mentions parameter must be AllowedMentions')
 | 
					            raise TypeError('allowed_mentions parameter must be AllowedMentions')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.allowed_mentions = allowed_mentions
 | 
					        self.allowed_mentions = allowed_mentions
 | 
				
			||||||
        # Only disable cache if both fetch_offline and guild_subscriptions are off.
 | 
					 | 
				
			||||||
        self._cache_members = (self._fetch_offline or self.guild_subscriptions)
 | 
					 | 
				
			||||||
        self._chunk_requests = []
 | 
					        self._chunk_requests = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        activity = options.get('activity', None)
 | 
					        activity = options.get('activity', None)
 | 
				
			||||||
@@ -142,6 +140,16 @@ class ConnectionState:
 | 
				
			|||||||
            if not intents.members and self._fetch_offline:
 | 
					            if not intents.members and self._fetch_offline:
 | 
				
			||||||
                raise ValueError('Intents.members has be enabled to fetch offline members.')
 | 
					                raise ValueError('Intents.members has be enabled to fetch offline members.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cache_flags = options.get('member_cache_flags', None)
 | 
				
			||||||
 | 
					        if cache_flags is None:
 | 
				
			||||||
 | 
					            cache_flags = MemberCacheFlags.all()
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            if not isinstance(cache_flags, MemberCacheFlags):
 | 
				
			||||||
 | 
					                raise TypeError('member_cache_flags parameter must be MemberCacheFlags not %r' % type(cache_flags))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cache_flags._verify_intents(intents)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self._member_cache_flags = cache_flags
 | 
				
			||||||
        self._activity = activity
 | 
					        self._activity = activity
 | 
				
			||||||
        self._status = status
 | 
					        self._status = status
 | 
				
			||||||
        self._intents = intents
 | 
					        self._intents = intents
 | 
				
			||||||
@@ -564,6 +572,7 @@ class ConnectionState:
 | 
				
			|||||||
        user = data['user']
 | 
					        user = data['user']
 | 
				
			||||||
        member_id = int(user['id'])
 | 
					        member_id = int(user['id'])
 | 
				
			||||||
        member = guild.get_member(member_id)
 | 
					        member = guild.get_member(member_id)
 | 
				
			||||||
 | 
					        flags = self._member_cache_flags
 | 
				
			||||||
        if member is None:
 | 
					        if member is None:
 | 
				
			||||||
            if 'username' not in user:
 | 
					            if 'username' not in user:
 | 
				
			||||||
                # sometimes we receive 'incomplete' member data post-removal.
 | 
					                # sometimes we receive 'incomplete' member data post-removal.
 | 
				
			||||||
@@ -571,13 +580,17 @@ class ConnectionState:
 | 
				
			|||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            member, old_member = Member._from_presence_update(guild=guild, data=data, state=self)
 | 
					            member, old_member = Member._from_presence_update(guild=guild, data=data, state=self)
 | 
				
			||||||
            guild._add_member(member)
 | 
					            if flags.online or (flags._online_only and member.raw_status != 'offline'):
 | 
				
			||||||
 | 
					                guild._add_member(member)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            old_member = Member._copy(member)
 | 
					            old_member = Member._copy(member)
 | 
				
			||||||
            user_update = member._presence_update(data=data, user=user)
 | 
					            user_update = member._presence_update(data=data, user=user)
 | 
				
			||||||
            if user_update:
 | 
					            if user_update:
 | 
				
			||||||
                self.dispatch('user_update', user_update[0], user_update[1])
 | 
					                self.dispatch('user_update', user_update[0], user_update[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if flags._online_only and member.raw_status == 'offline':
 | 
				
			||||||
 | 
					                guild._remove_member(member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.dispatch('member_update', old_member, member)
 | 
					        self.dispatch('member_update', old_member, member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def parse_user_update(self, data):
 | 
					    def parse_user_update(self, data):
 | 
				
			||||||
@@ -697,7 +710,7 @@ class ConnectionState:
 | 
				
			|||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        member = Member(guild=guild, data=data, state=self)
 | 
					        member = Member(guild=guild, data=data, state=self)
 | 
				
			||||||
        if self._cache_members:
 | 
					        if self._member_cache_flags.joined:
 | 
				
			||||||
            guild._add_member(member)
 | 
					            guild._add_member(member)
 | 
				
			||||||
        guild._member_count += 1
 | 
					        guild._member_count += 1
 | 
				
			||||||
        self.dispatch('member_join', member)
 | 
					        self.dispatch('member_join', member)
 | 
				
			||||||
@@ -760,7 +773,7 @@ class ConnectionState:
 | 
				
			|||||||
        return self._add_guild_from_data(data)
 | 
					        return self._add_guild_from_data(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def chunk_guild(self, guild, *, wait=True, cache=None):
 | 
					    async def chunk_guild(self, guild, *, wait=True, cache=None):
 | 
				
			||||||
        cache = cache or self._cache_members
 | 
					        cache = cache or self._member_cache_flags.joined
 | 
				
			||||||
        future = self.loop.create_future()
 | 
					        future = self.loop.create_future()
 | 
				
			||||||
        request = ChunkRequest(guild.id, future, self._get_guild, cache=cache)
 | 
					        request = ChunkRequest(guild.id, future, self._get_guild, cache=cache)
 | 
				
			||||||
        self._chunk_requests.append(request)
 | 
					        self._chunk_requests.append(request)
 | 
				
			||||||
@@ -926,6 +939,7 @@ class ConnectionState:
 | 
				
			|||||||
    def parse_voice_state_update(self, data):
 | 
					    def parse_voice_state_update(self, data):
 | 
				
			||||||
        guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
 | 
					        guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
 | 
				
			||||||
        channel_id = utils._get_as_snowflake(data, 'channel_id')
 | 
					        channel_id = utils._get_as_snowflake(data, 'channel_id')
 | 
				
			||||||
 | 
					        flags = self._member_cache_flags
 | 
				
			||||||
        if guild is not None:
 | 
					        if guild is not None:
 | 
				
			||||||
            if int(data['user_id']) == self.user.id:
 | 
					            if int(data['user_id']) == self.user.id:
 | 
				
			||||||
                voice = self._get_voice_client(guild.id)
 | 
					                voice = self._get_voice_client(guild.id)
 | 
				
			||||||
@@ -935,6 +949,13 @@ class ConnectionState:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            member, before, after = guild._update_voice_state(data, channel_id)
 | 
					            member, before, after = guild._update_voice_state(data, channel_id)
 | 
				
			||||||
            if member is not None:
 | 
					            if member is not None:
 | 
				
			||||||
 | 
					                if flags.voice:
 | 
				
			||||||
 | 
					                    if channel_id is None and flags.value == MemberCacheFlags.voice.flag:
 | 
				
			||||||
 | 
					                        # Only remove from cache iff we only have the voice flag enabled
 | 
				
			||||||
 | 
					                        guild._remove_member(member)
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        guild._add_member(member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                self.dispatch('voice_state_update', member, before, after)
 | 
					                self.dispatch('voice_state_update', member, before, after)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                log.debug('VOICE_STATE_UPDATE referencing an unknown member ID: %s. Discarding.', data['user_id'])
 | 
					                log.debug('VOICE_STATE_UPDATE referencing an unknown member ID: %s. Discarding.', data['user_id'])
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								docs/api.rst
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								docs/api.rst
									
									
									
									
									
								
							@@ -2816,6 +2816,18 @@ AllowedMentions
 | 
				
			|||||||
.. autoclass:: AllowedMentions
 | 
					.. autoclass:: AllowedMentions
 | 
				
			||||||
    :members:
 | 
					    :members:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Intents
 | 
				
			||||||
 | 
					~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. autoclass:: Intents
 | 
				
			||||||
 | 
					    :members:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MemberCacheFlags
 | 
				
			||||||
 | 
					~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. autoclass:: MemberCacheFlags
 | 
				
			||||||
 | 
					    :members:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
File
 | 
					File
 | 
				
			||||||
~~~~~
 | 
					~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user