2525
2626from __future__ import annotations
2727
28- from typing import TYPE_CHECKING , Any , Final , TypeVar
28+ from enum import IntEnum
29+ from typing import TYPE_CHECKING , Any , TypeVar
2930
3031from .asset import Asset
3132from .colour import Colour
3637from .utils import (
3738 MISSING ,
3839 _bytes_to_base64_data ,
40+ cached_slot_property ,
41+ deprecated ,
3942 snowflake_time ,
4043)
4144
@@ -109,6 +112,43 @@ def _parse_tag_int(data: RoleTagPayload, key: str) -> int | None:
109112 return None
110113
111114
115+ class RoleType (IntEnum ):
116+ """Represents the type of role.
117+
118+ This is NOT provided by discord but is rather computed by pycord based on the role tags.
119+
120+ .. versionadded:: 2.7
121+
122+ Attributes
123+ ----------
124+ APPLICATION: :class:`int`
125+ The role is an application role.
126+ BOOSTER: :class:`int`
127+ The role is a guild's booster role.
128+ GUILD_PRODUCT: :class:`int`
129+ The role is a guild product role.
130+ PREMIUM_SUBSCRIPTION_BASE: :class:`int`
131+ The role is a base subscription role.
132+ PREMIUM_SUBSCRIPTION_TIER: :class:`int`
133+ The role is a subscription role.
134+ DRAFT_PREMIUM_SUBSCRIPTION_TIER: :class:`int`
135+ The role is a draft subscription role.
136+ INTEGRATION: :class:`int`
137+ The role is an integration role.
138+ CONNECTION: :class:`int`
139+ The role is a guild connections role.
140+ """
141+
142+ APPLICATION = 1
143+ BOOSTER = 2
144+ GUILD_PRODUCT = 3
145+ PREMIUM_SUBSCRIPTION_BASE = 4 # Not possible to determine currently, will be INTEGRATION if it's a base subscription
146+ PREMIUM_SUBSCRIPTION_TIER = 5
147+ DRAFT_PREMIUM_SUBSCRIPTION_TIER = 5
148+ INTEGRATION = 7
149+ CONNECTION = 8
150+
151+
112152class RoleTags :
113153 """Represents tags on a role.
114154
@@ -142,6 +182,7 @@ class RoleTags:
142182 "_guild_connections" ,
143183 "bot_id" ,
144184 "_data" ,
185+ "_type" ,
145186 )
146187
147188 def __init__ (self , data : RoleTagPayload ):
@@ -161,102 +202,73 @@ def __init__(self, data: RoleTagPayload):
161202 data , "available_for_purchase"
162203 )
163204
164- @property
165- def is_bot_role (self ) -> bool :
166- """Whether the role is associated with a bot.
167- .. versionadded:: 2.7
168- """
205+ @cached_slot_property ("_type" )
206+ def type (self ) -> RoleType :
207+ """Determine the role type based on tag flags."""
208+ # Bot role
209+ if self .bot_id is not None :
210+ return RoleType .APPLICATION
211+
212+ # Role connection
213+ if self ._guild_connections is True :
214+ return RoleType .CONNECTION
215+
216+ # Paid roles
217+ if self ._guild_connections is False :
218+ if self ._premium_subscriber is False :
219+ return RoleType .GUILD_PRODUCT
220+
221+ if self ._premium_subscriber is True :
222+ return RoleType .BOOSTER
223+
224+ # subscription roles
225+ if self .integration_id is not None :
226+ if (
227+ self ._premium_subscriber is None
228+ and self .subscription_listing_id is not None
229+ ):
230+ if self ._available_for_purchase is True :
231+ return RoleType .PREMIUM_SUBSCRIPTION_TIER
232+ return RoleType .DRAFT_PREMIUM_SUBSCRIPTION_TIER
233+
234+ # integration role (Twitch/YouTube)
235+ if self .integration_id is not None :
236+ return RoleType .INTEGRATION
237+
238+ raise ValueError ("Unable to determine the role type based on provided tags." )
239+
240+ @deprecated ("RoleTags.type" , "2.7" )
241+ def is_bot_managed (self ) -> bool :
242+ """Whether the role is associated with a bot."""
169243 return self .bot_id is not None
170244
171- @property
172- def is_booster_role (self ) -> bool :
173- """Whether the role is the "boost", role for the guild.
174- .. versionadded:: 2.7
175- """
176- return self ._guild_connections is False and self ._premium_subscriber is True
177-
178- @property
179- def is_guild_product_role (self ) -> bool :
180- """Whether the role is a guild product role.
181-
182- .. versionadded:: 2.7
183- """
184- return self ._guild_connections is False and self ._premium_subscriber is False
245+ @deprecated ("RoleTags.type" , "2.7" )
246+ def is_premium_subscriber (self ) -> bool :
247+ """Whether the role is the premium subscriber, AKA "boost", role for the guild."""
248+ return self ._premium_subscriber is None
185249
186- @property
250+ @deprecated ( "RoleTags.type" , "2.7" )
187251 def is_integration (self ) -> bool :
188252 """Whether the guild manages the role through some form of
189253 integrations such as Twitch or through guild subscriptions.
190254 """
191255 return self .integration_id is not None
192256
193- @property
194- def is_base_subscription_role (self ) -> bool :
195- """Whether the role is a base subscription role.
196-
197- .. versionadded:: 2.7
198- """
199- return (
200- self ._guild_connections is False
201- and self ._premium_subscriber is False
202- and self .integration_id is not None
203- )
204-
205- @property
206- def is_subscription_role (self ) -> bool :
207- """Whether the role is a subscription role.
208-
209- .. versionadded:: 2.7
210- """
211- return (
212- self ._guild_connections is False
213- and self ._premium_subscriber is None
214- and self .integration_id is not None
215- and self .subscription_listing_id is not None
216- and self ._available_for_purchase is True
217- )
218-
219- @property
220- def is_draft_subscription_role (self ) -> bool :
221- """Whether the role is a draft subscription role.
257+ @deprecated ("RoleTags.type" , "2.7" )
258+ def is_available_for_purchase (self ) -> bool :
259+ """Whether the role is available for purchase."""
260+ return self ._available_for_purchase is True
222261
223- .. versionadded:: 2.7
224- """
225- return (
226- self ._guild_connections is False
227- and self ._premium_subscriber is None
228- and self .subscription_listing_id is not None
229- and self .integration_id is not None
230- and self ._available_for_purchase is False
231- )
232-
233- @property
262+ @deprecated ("RoleTags.type" , "2.7" )
234263 def is_guild_connections_role (self ) -> bool :
235- """Whether the role is a guild connections role.
236-
237- .. versionadded:: 2.7
238- """
264+ """Whether the role is a guild connections role."""
239265 return self ._guild_connections is True
240266
241- QUALIFIERS : Final = (
242- "is_bot_role" ,
243- "is_booster_role" ,
244- "is_guild_product_role" ,
245- "is_integration" ,
246- "is_base_subscription_role" ,
247- "is_subscription_role" ,
248- "is_draft_subscription_role" ,
249- "is_guild_connections_role" ,
250- )
251-
252267 def __repr__ (self ) -> str :
253268 return (
254269 f"<RoleTags bot_id={ self .bot_id } integration_id={ self .integration_id } "
255270 + f"subscription_listing_id={ self .subscription_listing_id } "
256- + " " .join (
257- q .removeprefix ("is_" ) for q in self .QUALIFIERS if getattr (self , q )
258- )
259- + ">"
271+ + f"type={ self .type !r} >"
260272 )
261273
262274
@@ -431,6 +443,28 @@ def is_default(self) -> bool:
431443 """Checks if the role is the default role."""
432444 return self .guild .id == self .id
433445
446+ @deprecated ("Role.type" , "2.7" )
447+ def is_bot_managed (self ) -> bool :
448+ """Whether the role is associated with a bot.
449+ .. versionadded:: 1.6
450+ """
451+ return self .tags is not None and self .tags .is_bot_managed ()
452+
453+ @deprecated ("Role.type" , "2.7" )
454+ def is_premium_subscriber (self ) -> bool :
455+ """Whether the role is the premium subscriber, AKA "boost", role for the guild.
456+ .. versionadded:: 1.6
457+ """
458+ return self .tags is not None and self .tags .is_premium_subscriber ()
459+
460+ @deprecated ("Role.type" , "2.7" )
461+ def is_integration (self ) -> bool :
462+ """Whether the guild manages the role through some form of
463+ integrations such as Twitch or through guild subscriptions.
464+ .. versionadded:: 1.6
465+ """
466+ return self .tags is not None and self .tags .is_integration ()
467+
434468 def is_assignable (self ) -> bool :
435469 """Whether the role is able to be assigned or removed by the bot.
436470
@@ -443,6 +477,23 @@ def is_assignable(self) -> bool:
443477 and (me .top_role > self or me .id == self .guild .owner_id )
444478 )
445479
480+ @deprecated ("Role.type" , "2.7" )
481+ def is_available_for_purchase (self ) -> bool :
482+ """Whether the role is available for purchase.
483+ Returns ``True`` if the role is available for purchase, and
484+ ``False`` if it is not available for purchase or if the
485+ role is not linked to a guild subscription.
486+ .. versionadded:: 2.7
487+ """
488+ return self .tags is not None and self .tags .is_available_for_purchase ()
489+
490+ @deprecated ("Role.type" , "2.7" )
491+ def is_guild_connections_role (self ) -> bool :
492+ """Whether the role is a guild connections role.
493+ .. versionadded:: 2.7
494+ """
495+ return self .tags is not None and self .tags .is_guild_connections_role ()
496+
446497 @property
447498 def permissions (self ) -> Permissions :
448499 """Returns the role's permissions."""
@@ -489,6 +540,14 @@ def icon(self) -> Asset | None:
489540
490541 return Asset ._from_icon (self ._state , self .id , self ._icon , "role" )
491542
543+ @property
544+ def type (self ) -> RoleType :
545+ """The type of the role.
546+
547+ .. versionadded:: 2.7
548+ """
549+ return self .tags .type
550+
492551 async def _move (self , position : int , reason : str | None ) -> None :
493552 if position <= 0 :
494553 raise InvalidArgument ("Cannot move role to position 0 or below" )
0 commit comments