Implement role tags.

This comes with:

* The RoleTags class
* Role.is_premium_subscriber()
* Role.is_bot_managed()
* Role.is_integration()
* Guild.self_role
* Guild.premium_subscriber_role
This commit is contained in:
Rapptz 2020-11-26 01:55:25 -05:00
parent 4adbe03d7c
commit e65dab3b23
3 changed files with 108 additions and 4 deletions

View File

@ -564,6 +564,30 @@ class Guild(Hashable):
""":class:`Role`: Gets the @everyone role that all members have by default.""" """:class:`Role`: Gets the @everyone role that all members have by default."""
return self.get_role(self.id) return self.get_role(self.id)
@property
def premium_subscriber_role(self):
"""Optional[:class:`Role`]: Gets the premium subscriber role, AKA "boost" role, in this guild.
.. versionadded:: 1.6
"""
for role in self._roles.values():
if role.is_premium_subscriber():
return role
return None
@property
def self_role(self):
"""Optional[:class:`Role`]: Gets the role associated with this client's user, if any.
.. versionadded:: 1.6
"""
self_id = self._state.self_id
for role in self._roles.values():
tags = role.tags
if tags and tags.bot_id == self_id:
return role
return None
@property @property
def owner(self): def owner(self):
"""Optional[:class:`Member`]: The member that owns the guild.""" """Optional[:class:`Member`]: The member that owns the guild."""

View File

@ -28,7 +28,53 @@ from .permissions import Permissions
from .errors import InvalidArgument from .errors import InvalidArgument
from .colour import Colour from .colour import Colour
from .mixins import Hashable from .mixins import Hashable
from .utils import snowflake_time from .utils import snowflake_time, _get_as_snowflake
class RoleTags:
"""Represents tags on a role.
A role tag is a piece of extra information attached to a managed role
that gives it context for the reason the role is managed.
While this can be accessed, a useful interface is also provided in the
:class:`Role` and :class:`Guild` classes as well.
.. versionadded:: 1.6
Attributes
------------
bot_id: Optional[:class:`int`]
The bot's user ID that manages this role.
integration_id: Optional[:class:`int`]
The integration ID that manages the role.
"""
__slots__ = ('bot_id', 'integration_id', '_premium_subscriber',)
def __init__(self, data):
self.bot_id = _get_as_snowflake(data, 'bot_id')
self.integration_id = _get_as_snowflake(data, 'integration_id')
# NOTE: The API returns "null" for this if it's valid, which corresponds to None.
# This is different from other fields where "null" means "not there".
# So in this case, a value of None is the same as True.
# Which means we would need a different sentinel. For this purpose I used ellipsis.
self._premium_subscriber = data.get('premium_subscriber', ...)
def is_bot_managed(self):
""":class:`bool`: Whether the role is associated with a bot."""
return self.bot_id is not None
def is_premium_subscriber(self):
""":class:`bool`: Whether the role is the premium subscriber, AKA "boost", role for the guild."""
return self._premium_subscriber is None
def is_integration(self):
""":class:`bool`: Whether the role is managed by an integration."""
return self.integration_id is not None
def __repr__(self):
return '<RoleTags bot_id={0.bot_id} integration_id={0.integration_id} ' \
'premium_subscriber={1}>'.format(self, self.is_premium_subscriber())
class Role(Hashable): class Role(Hashable):
"""Represents a Discord role in a :class:`Guild`. """Represents a Discord role in a :class:`Guild`.
@ -85,10 +131,12 @@ class Role(Hashable):
integrations such as Twitch. integrations such as Twitch.
mentionable: :class:`bool` mentionable: :class:`bool`
Indicates if the role can be mentioned by users. Indicates if the role can be mentioned by users.
tags: Optional[:class:`RoleTags`]
The role tags associated with this role.
""" """
__slots__ = ('id', 'name', '_permissions', '_colour', 'position', __slots__ = ('id', 'name', '_permissions', '_colour', 'position',
'managed', 'mentionable', 'hoist', 'guild', '_state') 'managed', 'mentionable', 'hoist', 'guild', 'tags', '_state')
def __init__(self, *, guild, state, data): def __init__(self, *, guild, state, data):
self.guild = guild self.guild = guild
@ -147,10 +195,36 @@ class Role(Hashable):
self.managed = data.get('managed', False) self.managed = data.get('managed', False)
self.mentionable = data.get('mentionable', False) self.mentionable = data.get('mentionable', False)
try:
self.tags = RoleTags(data['tags'])
except KeyError:
self.tags = None
def is_default(self): def is_default(self):
""":class:`bool`: Checks if the role is the default role.""" """:class:`bool`: Checks if the role is the default role."""
return self.guild.id == self.id return self.guild.id == self.id
def is_bot_managed(self):
""":class:`bool`: Whether the role is associated with a bot.
.. versionadded:: 1.6
"""
return self.tags is not None and self.tags.is_bot_managed()
def is_premium_subscriber(self):
""":class:`bool`: Whether the role is the premium subscriber, AKA "boost", role for the guild.
.. versionadded:: 1.6
"""
return self.tags is not None and self.tags.is_premium_subscriber()
def is_integration(self):
""":class:`bool`: Whether the role is managed by an integration.
.. versionadded:: 1.6
"""
return self.tags is not None and self.tags.is_integration()
@property @property
def permissions(self): def permissions(self):
""":class:`Permissions`: Returns the role's permissions.""" """:class:`Permissions`: Returns the role's permissions."""
@ -218,7 +292,7 @@ class Role(Hashable):
use this. use this.
All fields are optional. All fields are optional.
.. versionchanged:: 1.4 .. versionchanged:: 1.4
Can now pass ``int`` to ``colour`` keyword-only parameter. Can now pass ``int`` to ``colour`` keyword-only parameter.
@ -260,7 +334,7 @@ class Role(Hashable):
colour = fields['colour'] colour = fields['colour']
except KeyError: except KeyError:
colour = fields.get('color', self.colour) colour = fields.get('color', self.colour)
if isinstance(colour, int): if isinstance(colour, int):
colour = Colour(value=colour) colour = Colour(value=colour)

View File

@ -2733,6 +2733,12 @@ Role
.. autoclass:: Role() .. autoclass:: Role()
:members: :members:
RoleTags
~~~~~~~~~~
.. autoclass:: RoleTags()
:members:
TextChannel TextChannel
~~~~~~~~~~~~ ~~~~~~~~~~~~