25
25
26
26
from __future__ import annotations
27
27
28
- from typing import TYPE_CHECKING , Any , Final , TypeVar
28
+ from enum import IntEnum
29
+ from typing import TYPE_CHECKING , Any , TypeVar
29
30
30
31
from .asset import Asset
31
32
from .colour import Colour
36
37
from .utils import (
37
38
MISSING ,
38
39
_bytes_to_base64_data ,
40
+ cached_slot_property ,
41
+ deprecated ,
39
42
snowflake_time ,
40
43
)
41
44
@@ -109,6 +112,43 @@ def _parse_tag_int(data: RoleTagPayload, key: str) -> int | None:
109
112
return None
110
113
111
114
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
+
112
152
class RoleTags :
113
153
"""Represents tags on a role.
114
154
@@ -142,6 +182,7 @@ class RoleTags:
142
182
"_guild_connections" ,
143
183
"bot_id" ,
144
184
"_data" ,
185
+ "_type" ,
145
186
)
146
187
147
188
def __init__ (self , data : RoleTagPayload ):
@@ -161,102 +202,73 @@ def __init__(self, data: RoleTagPayload):
161
202
data , "available_for_purchase"
162
203
)
163
204
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."""
169
243
return self .bot_id is not None
170
244
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
181
249
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" )
187
251
def is_integration (self ) -> bool :
188
252
"""Whether the guild manages the role through some form of
189
253
integrations such as Twitch or through guild subscriptions.
190
254
"""
191
255
return self .integration_id is not None
192
256
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
208
261
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" )
234
263
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."""
239
265
return self ._guild_connections is True
240
266
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
-
252
267
def __repr__ (self ) -> str :
253
268
return (
254
269
f"<RoleTags bot_id={ self .bot_id } integration_id={ self .integration_id } "
255
270
+ 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} >"
260
272
)
261
273
262
274
@@ -431,6 +443,31 @@ def is_default(self) -> bool:
431
443
"""Checks if the role is the default role."""
432
444
return self .guild .id == self .id
433
445
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
+
434
471
def is_assignable (self ) -> bool :
435
472
"""Whether the role is able to be assigned or removed by the bot.
436
473
@@ -443,6 +480,25 @@ def is_assignable(self) -> bool:
443
480
and (me .top_role > self or me .id == self .guild .owner_id )
444
481
)
445
482
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
+
446
502
@property
447
503
def permissions (self ) -> Permissions :
448
504
"""Returns the role's permissions."""
@@ -489,6 +545,14 @@ def icon(self) -> Asset | None:
489
545
490
546
return Asset ._from_icon (self ._state , self .id , self ._icon , "role" )
491
547
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
+
492
556
async def _move (self , position : int , reason : str | None ) -> None :
493
557
if position <= 0 :
494
558
raise InvalidArgument ("Cannot move role to position 0 or below" )
0 commit comments