aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2020-11-26 01:55:25 -0500
committerRapptz <[email protected]>2020-11-26 01:57:24 -0500
commite65dab3b233a78761eef4713aba58eafca7acb18 (patch)
tree2d61c50d87b967839256865eaf8dfd1cae83450f
parent[commands] Allow setting description of cogs (diff)
downloaddiscord.py-e65dab3b233a78761eef4713aba58eafca7acb18.tar.xz
discord.py-e65dab3b233a78761eef4713aba58eafca7acb18.zip
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
-rw-r--r--discord/guild.py24
-rw-r--r--discord/role.py82
-rw-r--r--docs/api.rst6
3 files changed, 108 insertions, 4 deletions
diff --git a/discord/guild.py b/discord/guild.py
index b5a9b864..2cab0053 100644
--- a/discord/guild.py
+++ b/discord/guild.py
@@ -565,6 +565,30 @@ class Guild(Hashable):
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
def owner(self):
"""Optional[:class:`Member`]: The member that owns the guild."""
return self.get_member(self.owner_id)
diff --git a/discord/role.py b/discord/role.py
index 882f346e..bc50fdbb 100644
--- a/discord/role.py
+++ b/discord/role.py
@@ -28,7 +28,53 @@ from .permissions import Permissions
from .errors import InvalidArgument
from .colour import Colour
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):
"""Represents a Discord role in a :class:`Guild`.
@@ -85,10 +131,12 @@ class Role(Hashable):
integrations such as Twitch.
mentionable: :class:`bool`
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',
- 'managed', 'mentionable', 'hoist', 'guild', '_state')
+ 'managed', 'mentionable', 'hoist', 'guild', 'tags', '_state')
def __init__(self, *, guild, state, data):
self.guild = guild
@@ -147,10 +195,36 @@ class Role(Hashable):
self.managed = data.get('managed', False)
self.mentionable = data.get('mentionable', False)
+ try:
+ self.tags = RoleTags(data['tags'])
+ except KeyError:
+ self.tags = None
+
def is_default(self):
""":class:`bool`: Checks if the role is the default role."""
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
def permissions(self):
""":class:`Permissions`: Returns the role's permissions."""
@@ -218,7 +292,7 @@ class Role(Hashable):
use this.
All fields are optional.
-
+
.. versionchanged:: 1.4
Can now pass ``int`` to ``colour`` keyword-only parameter.
@@ -260,7 +334,7 @@ class Role(Hashable):
colour = fields['colour']
except KeyError:
colour = fields.get('color', self.colour)
-
+
if isinstance(colour, int):
colour = Colour(value=colour)
diff --git a/docs/api.rst b/docs/api.rst
index 60923557..f1a7b0ca 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -2733,6 +2733,12 @@ Role
.. autoclass:: Role()
:members:
+RoleTags
+~~~~~~~~~~
+
+.. autoclass:: RoleTags()
+ :members:
+
TextChannel
~~~~~~~~~~~~