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.
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
181249
182- .. versionadded:: 2.7
183- """
184- return self ._guild_connections is False and self ._premium_subscriber is False
185-
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.
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
208261
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.
222-
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,31 @@ 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+
450+ .. versionadded:: 1.6
451+ """
452+ return self .tags is not None and self .tags .is_bot_managed ()
453+
454+ @deprecated ("Role.type" , "2.7" )
455+ def is_premium_subscriber (self ) -> bool :
456+ """Whether the role is the premium subscriber, AKA "boost", role for the guild.
457+
458+ .. versionadded:: 1.6
459+ """
460+ return self .tags is not None and self .tags .is_premium_subscriber ()
461+
462+ @deprecated ("Role.type" , "2.7" )
463+ def is_integration (self ) -> bool :
464+ """Whether the guild manages the role through some form of
465+ integrations such as Twitch or through guild subscriptions.
466+
467+ .. versionadded:: 1.6
468+ """
469+ return self .tags is not None and self .tags .is_integration ()
470+
434471 def is_assignable (self ) -> bool :
435472 """Whether the role is able to be assigned or removed by the bot.
436473
@@ -443,6 +480,25 @@ def is_assignable(self) -> bool:
443480 and (me .top_role > self or me .id == self .guild .owner_id )
444481 )
445482
483+ @deprecated ("Role.type" , "2.7" )
484+ def is_available_for_purchase (self ) -> bool :
485+ """Whether the role is available for purchase.
486+ Returns ``True`` if the role is available for purchase, and
487+ ``False`` if it is not available for purchase or if the
488+ role is not linked to a guild subscription.
489+
490+ .. versionadded:: 2.7
491+ """
492+ return self .tags is not None and self .tags .is_available_for_purchase ()
493+
494+ @deprecated ("Role.type" , "2.7" )
495+ def is_guild_connections_role (self ) -> bool :
496+ """Whether the role is a guild connections role.
497+
498+ .. versionadded:: 2.7
499+ """
500+ return self .tags is not None and self .tags .is_guild_connections_role ()
501+
446502 @property
447503 def permissions (self ) -> Permissions :
448504 """Returns the role's permissions."""
@@ -489,6 +545,14 @@ def icon(self) -> Asset | None:
489545
490546 return Asset ._from_icon (self ._state , self .id , self ._icon , "role" )
491547
548+ @property
549+ def type (self ) -> RoleType :
550+ """The type of the role.
551+
552+ .. versionadded:: 2.7
553+ """
554+ return self .tags .type
555+
492556 async def _move (self , position : int , reason : str | None ) -> None :
493557 if position <= 0 :
494558 raise InvalidArgument ("Cannot move role to position 0 or below" )
0 commit comments