Skip to content

Role

Role

Bases: DiscordObject

Source code in interactions/models/discord/role.py
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
@attrs.define(eq=False, order=False, hash=False, kw_only=True)
@total_ordering
class Role(DiscordObject):
    _sentinel = object()

    name: str = attrs.field(repr=True)
    color: "Color" = attrs.field(repr=False, converter=Color)
    hoist: bool = attrs.field(repr=False, default=False)
    position: int = attrs.field(repr=True)
    permissions: "Permissions" = attrs.field(repr=False, converter=Permissions)
    managed: bool = attrs.field(repr=False, default=False)
    mentionable: bool = attrs.field(repr=False, default=True)
    premium_subscriber: bool = attrs.field(
        repr=False, default=_sentinel, converter=partial(sentinel_converter, sentinel=_sentinel)
    )
    subscription_listing_id: "Snowflake_Type | None" = attrs.field(default=None, repr=False)
    purchasable_or_has_subscribers: bool = attrs.field(default=False)
    _icon: Asset | None = attrs.field(repr=False, default=None)
    _unicode_emoji: PartialEmoji | None = attrs.field(
        repr=False, default=None, converter=optional_c(PartialEmoji.from_str)
    )
    _guild_id: "Snowflake_Type" = attrs.field(
        repr=False,
    )
    _bot_id: "Snowflake_Type | None" = attrs.field(repr=False, default=None)
    _integration_id: "Snowflake_Type | None" = attrs.field(repr=False, default=None)  # todo integration object?
    _guild_connections: bool = attrs.field(repr=False, default=False)

    def __lt__(self: "Role", other: "Role") -> bool:
        if not isinstance(self, Role) or not isinstance(other, Role):
            return NotImplemented

        if self._guild_id != other._guild_id:
            raise RuntimeError("Unable to compare Roles from different guilds.")

        if self.id == self._guild_id:  # everyone role
            # everyone role is on the bottom, so check if the other role is, well, not it
            # because then it must be higher than it
            return other.id != self.id

        if self.position < other.position:
            return True

        return self.id < other.id if self.position == other.position else False

    @classmethod
    def _process_dict(cls, data: dict[str, Any], client: "Client") -> dict[str, Any]:
        data |= data.pop("tags", {})

        if icon_hash := data.get("icon"):
            data["icon"] = Asset.from_path_hash(client, f"role-icons/{data['id']}/{{}}", icon_hash)

        data["premium_subscriber"] = nulled_boolean_get(data, "premium_subscriber")
        data["guild_connections"] = nulled_boolean_get(data, "guild_connections")
        data["available_for_purchase"] = nulled_boolean_get(data, "available_for_purchase")

        return data

    async def fetch_bot(self, *, force: bool = False) -> "Member | None":
        """
        Fetch the bot associated with this role if any.

        Args:
            force: Whether to force fetch the bot from the API.

        Returns:
            Member object if any

        """
        if self._bot_id is None:
            return None
        return await self._client.cache.fetch_member(self._guild_id, self._bot_id, force=force)

    def get_bot(self) -> "Member | None":
        """
        Get the bot associated with this role if any.

        Returns:
            Member object if any

        """
        if self._bot_id is None:
            return None
        return self._client.cache.get_member(self._guild_id, self._bot_id)

    @property
    def guild(self) -> "Guild":
        """The guild object this role is from."""
        return self._client.cache.get_guild(self._guild_id)  # pyright: ignore [reportGeneralTypeIssues]

    @property
    def default(self) -> bool:
        """Is this the `@everyone` role."""
        return self.id == self._guild_id

    @property
    def bot_managed(self) -> bool:
        """Is this role owned/managed by a bot."""
        return self._bot_id is not None

    @property
    def is_linked_role(self) -> bool:
        """Is this role a linked role."""
        return self._guild_connections

    @property
    def mention(self) -> str:
        """Returns a string that would mention the role."""
        return f"<@&{self.id}>" if self.id != self._guild_id else "@everyone"

    @property
    def integration(self) -> bool:
        """Is this role owned/managed by an integration."""
        return self._integration_id is not None

    @property
    def members(self) -> list["Member"]:
        """List of members with this role"""
        return [member for member in self.guild.members if member.has_role(self)]

    @property
    def icon(self) -> Asset | PartialEmoji | None:
        """
        The icon of this role

        !!! note
            You have to use this method instead of the `_icon` attribute, because the first does account for unicode emojis
        """
        return self._icon or self._unicode_emoji

    @property
    def is_assignable(self) -> bool:
        """
        Can this role be assigned or removed by this bot?

        !!! note
            This does not account for permissions, only the role hierarchy

        """
        return (self.default or self.guild.me.top_role > self) and not self.managed

    async def delete(self, reason: str | Missing = MISSING) -> None:
        """
        Delete this role.

        Args:
            reason: An optional reason for this deletion

        """
        await self._client.http.delete_guild_role(self._guild_id, self.id, reason)

    async def edit(
        self,
        *,
        name: str | None = None,
        permissions: str | None = None,
        color: Color | COLOR_TYPES | None = None,
        hoist: bool | None = None,
        mentionable: bool | None = None,
        icon: bytes | UPLOADABLE_TYPE | None = None,
        unicode_emoji: str | None = None,
    ) -> "Role":
        """
        Edit this role, all arguments are optional.

        Args:
            name: name of the role
            permissions: New permissions to use
            color: The color of the role
            hoist: whether the role should be displayed separately in the sidebar
            mentionable: whether the role should be mentionable
            icon: (Guild Level 2+) Bytes-like object representing the icon; supports PNG, JPEG and WebP
            unicode_emoji: (Guild Level 2+) Unicode emoji for the role; can't be used with icon

        Returns:
            Role with updated information

        """
        color = process_color(color)

        if icon and unicode_emoji:
            raise ValueError("Cannot pass both icon and unicode_emoji")
        if icon:
            icon = to_image_data(icon)

        payload = dict_filter(
            {
                "name": name,
                "permissions": permissions,
                "color": color,
                "hoist": hoist,
                "mentionable": mentionable,
                "icon": icon,
                "unicode_emoji": unicode_emoji,
            }
        )

        r_data = await self._client.http.modify_guild_role(self._guild_id, self.id, payload)
        r_data = dict(r_data)  # to convert typed dict to regular dict
        r_data["guild_id"] = self._guild_id
        return self.from_dict(r_data, self._client)

    async def move(self, position: int, reason: str | Missing = MISSING) -> "Role":
        """
        Move this role to a new position.

        Args:
            position: The new position of the role
            reason: An optional reason for this move

        Returns:
            The role object

        """
        await self._client.http.modify_guild_role_positions(
            self._guild_id, [{"id": self.id, "position": position}], reason
        )
        return self

bot_managed: bool property

Is this role owned/managed by a bot.

default: bool property

Is this the @everyone role.

guild: Guild property

The guild object this role is from.

icon: Asset | PartialEmoji | None property

The icon of this role

Note

You have to use this method instead of the _icon attribute, because the first does account for unicode emojis

integration: bool property

Is this role owned/managed by an integration.

is_assignable: bool property

Can this role be assigned or removed by this bot?

Note

This does not account for permissions, only the role hierarchy

is_linked_role: bool property

Is this role a linked role.

members: list[Member] property

List of members with this role

mention: str property

Returns a string that would mention the role.

delete(reason=MISSING) async

Delete this role.

Parameters:

Name Type Description Default
reason str | Missing

An optional reason for this deletion

MISSING
Source code in interactions/models/discord/role.py
172
173
174
175
176
177
178
179
180
async def delete(self, reason: str | Missing = MISSING) -> None:
    """
    Delete this role.

    Args:
        reason: An optional reason for this deletion

    """
    await self._client.http.delete_guild_role(self._guild_id, self.id, reason)

edit(*, name=None, permissions=None, color=None, hoist=None, mentionable=None, icon=None, unicode_emoji=None) async

Edit this role, all arguments are optional.

Parameters:

Name Type Description Default
name str | None

name of the role

None
permissions str | None

New permissions to use

None
color Color | COLOR_TYPES | None

The color of the role

None
hoist bool | None

whether the role should be displayed separately in the sidebar

None
mentionable bool | None

whether the role should be mentionable

None
icon bytes | UPLOADABLE_TYPE | None

(Guild Level 2+) Bytes-like object representing the icon; supports PNG, JPEG and WebP

None
unicode_emoji str | None

(Guild Level 2+) Unicode emoji for the role; can't be used with icon

None

Returns:

Type Description
Role

Role with updated information

Source code in interactions/models/discord/role.py
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
async def edit(
    self,
    *,
    name: str | None = None,
    permissions: str | None = None,
    color: Color | COLOR_TYPES | None = None,
    hoist: bool | None = None,
    mentionable: bool | None = None,
    icon: bytes | UPLOADABLE_TYPE | None = None,
    unicode_emoji: str | None = None,
) -> "Role":
    """
    Edit this role, all arguments are optional.

    Args:
        name: name of the role
        permissions: New permissions to use
        color: The color of the role
        hoist: whether the role should be displayed separately in the sidebar
        mentionable: whether the role should be mentionable
        icon: (Guild Level 2+) Bytes-like object representing the icon; supports PNG, JPEG and WebP
        unicode_emoji: (Guild Level 2+) Unicode emoji for the role; can't be used with icon

    Returns:
        Role with updated information

    """
    color = process_color(color)

    if icon and unicode_emoji:
        raise ValueError("Cannot pass both icon and unicode_emoji")
    if icon:
        icon = to_image_data(icon)

    payload = dict_filter(
        {
            "name": name,
            "permissions": permissions,
            "color": color,
            "hoist": hoist,
            "mentionable": mentionable,
            "icon": icon,
            "unicode_emoji": unicode_emoji,
        }
    )

    r_data = await self._client.http.modify_guild_role(self._guild_id, self.id, payload)
    r_data = dict(r_data)  # to convert typed dict to regular dict
    r_data["guild_id"] = self._guild_id
    return self.from_dict(r_data, self._client)

fetch_bot(*, force=False) async

Fetch the bot associated with this role if any.

Parameters:

Name Type Description Default
force bool

Whether to force fetch the bot from the API.

False

Returns:

Type Description
Member | None

Member object if any

Source code in interactions/models/discord/role.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
async def fetch_bot(self, *, force: bool = False) -> "Member | None":
    """
    Fetch the bot associated with this role if any.

    Args:
        force: Whether to force fetch the bot from the API.

    Returns:
        Member object if any

    """
    if self._bot_id is None:
        return None
    return await self._client.cache.fetch_member(self._guild_id, self._bot_id, force=force)

get_bot()

Get the bot associated with this role if any.

Returns:

Type Description
Member | None

Member object if any

Source code in interactions/models/discord/role.py
104
105
106
107
108
109
110
111
112
113
114
def get_bot(self) -> "Member | None":
    """
    Get the bot associated with this role if any.

    Returns:
        Member object if any

    """
    if self._bot_id is None:
        return None
    return self._client.cache.get_member(self._guild_id, self._bot_id)

move(position, reason=MISSING) async

Move this role to a new position.

Parameters:

Name Type Description Default
position int

The new position of the role

required
reason str | Missing

An optional reason for this move

MISSING

Returns:

Type Description
Role

The role object

Source code in interactions/models/discord/role.py
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
async def move(self, position: int, reason: str | Missing = MISSING) -> "Role":
    """
    Move this role to a new position.

    Args:
        position: The new position of the role
        reason: An optional reason for this move

    Returns:
        The role object

    """
    await self._client.http.modify_guild_role_positions(
        self._guild_id, [{"id": self.id, "position": position}], reason
    )
    return self