Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -3648,6 +3648,9 @@ async def create_role(
hoist: bool = ...,
display_icon: Union[bytes, str] = MISSING,
mentionable: bool = ...,
primary_color: Union[Colour, int, None] = ...,
secondary_color: Union[Colour, int, None] = ...,
tertiary_color: Union[Colour, int, None] = ...,
) -> Role:
...

Expand All @@ -3662,6 +3665,9 @@ async def create_role(
hoist: bool = ...,
display_icon: Union[bytes, str] = MISSING,
mentionable: bool = ...,
primary_color: Union[Colour, int, None] = ...,
secondary_color: Union[Colour, int, None] = ...,
tertiary_color: Union[Colour, int, None] = ...,
) -> Role:
...

Expand All @@ -3676,6 +3682,9 @@ async def create_role(
display_icon: Union[bytes, str] = MISSING,
mentionable: bool = MISSING,
reason: Optional[str] = None,
primary_color: Union[Colour, int, None] = MISSING,
secondary_color: Union[Colour, int, None] = MISSING,
tertiary_color: Union[Colour, int, None] = MISSING,
) -> Role:
"""|coro|

Expand Down Expand Up @@ -3704,6 +3713,14 @@ async def create_role(
colour: Union[:class:`Colour`, :class:`int`]
The colour for the role. Defaults to :meth:`Colour.default`.
This is aliased to ``color`` as well.
primary_color: Union[:class:`Colour`, :class:`int`, None]
The primary color for the role. If provided, must be an integer or :class:`Colour`.
secondary_color: Union[:class:`Colour`, :class:`int`, None]
The secondary color for the role. Requires ``primary_color`` to also be set.
tertiary_color: Union[:class:`Colour`, :class:`int`, None]
The tertiary_color color for the role. Used for holographic role.
The holographic preset is:
{"primary_color": 11127295, "secondary_color": 16759788, "tertiary_color": 16761760}
hoist: :class:`bool`
Indicates if the role should be shown separately in the member list.
Defaults to ``False``.
Expand Down Expand Up @@ -3744,6 +3761,46 @@ async def create_role(
else:
fields['color'] = actual_colour.value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the lines above should just be on colors.primary_color, not on color anymore.


solid_color_used = color is not MISSING or colour is not MISSING
colors_used = primary_color is not MISSING or secondary_color is not MISSING or tertiary_color is not MISSING
if solid_color_used and colors_used:
raise TypeError(
"You must choose either only solid color (color/colour) or colors (primary_color/secondary_color/tertiary_color), not both."
)

colors_payload: Dict[str, Any] = {}
if primary_color is not MISSING:
if primary_color is None:
colors_payload['primary_color'] = None
elif isinstance(primary_color, int):
colors_payload['primary_color'] = primary_color
else:
colors_payload['primary_color'] = primary_color.value
if secondary_color is not MISSING:
if secondary_color is None:
colors_payload['secondary_color'] = None
elif isinstance(secondary_color, int):
colors_payload['secondary_color'] = secondary_color
else:
colors_payload['secondary_color'] = secondary_color.value
if tertiary_color is not MISSING:
if tertiary_color is None:
colors_payload['tertiary_color'] = None
elif isinstance(tertiary_color, int):
colors_payload['tertiary_color'] = tertiary_color
else:
colors_payload['tertiary_color'] = tertiary_color.value

if colors_payload:
fields['colors'] = colors_payload

if not colors_payload:
actual_colour = colour or color or Colour.default()
if isinstance(actual_colour, int):
fields['color'] = actual_colour
else:
fields['color'] = actual_colour.value

if hoist is not MISSING:
fields['hoist'] = hoist

Expand Down
2 changes: 1 addition & 1 deletion discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -1894,7 +1894,7 @@ def edit_role(
self, guild_id: Snowflake, role_id: Snowflake, *, reason: Optional[str] = None, **fields: Any
) -> Response[role.Role]:
r = Route('PATCH', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
valid_keys = ('name', 'permissions', 'color', 'hoist', 'icon', 'unicode_emoji', 'mentionable')
valid_keys = ('name', 'permissions', 'color', 'hoist', 'icon', 'unicode_emoji', 'mentionable', 'colors')
payload = {k: v for k, v in fields.items() if k in valid_keys}
return self.request(r, json=payload, reason=reason)

Expand Down
65 changes: 65 additions & 0 deletions discord/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ class Role(Hashable):
'tags',
'_flags',
'_state',
'_primary_color',
'_secondary_color',
'_tertiary_color',
)

def __init__(self, *, guild: Guild, state: ConnectionState, data: RolePayload):
Expand Down Expand Up @@ -284,6 +287,10 @@ def _update(self, data: RolePayload):
self.mentionable: bool = data.get('mentionable', False)
self.tags: Optional[RoleTags]
self._flags: int = data.get('flags', 0)
colors = data.get('colors', {})
self._primary_color = colors.get('primary_color', None)
self._secondary_color = colors.get('secondary_color', None)
self._tertiary_color = colors.get('tertiary_color', None)

try:
self.tags = RoleTags(data['tags']) # pyright: ignore[reportTypedDictNotRequiredAccess]
Expand Down Expand Up @@ -323,6 +330,21 @@ def is_assignable(self) -> bool:
me = self.guild.me
return not self.is_default() and not self.managed and (me.top_role > self or me.id == self.guild.owner_id)

@property
def primary_color(self) -> Optional[Colour]:
"""Optional[:class:`Colour`]: The role's primary color."""
return Colour(self._primary_color) if self._primary_color is not None else None

@property
def secondary_color(self) -> Optional[Colour]:
"""Optional[:class:`Colour`]: The role's secondary color."""
return Colour(self._secondary_color) if self._secondary_color is not None else None

@property
def tertiary_color(self) -> Optional[Colour]:
"""Optional[:class:`Colour`]: The role's tertiary color."""
return Colour(self._tertiary_color) if self._tertiary_color is not None else None

@property
def permissions(self) -> Permissions:
""":class:`Permissions`: Returns the role's permissions."""
Expand Down Expand Up @@ -425,6 +447,9 @@ async def edit(
mentionable: bool = MISSING,
position: int = MISSING,
reason: Optional[str] = MISSING,
primary_color: Union[Colour, int, None] = MISSING,
secondary_color: Union[Colour, int, None] = MISSING,
tertiary_color: Union[Colour, int, None] = MISSING,
) -> Optional[Role]:
"""|coro|

Expand Down Expand Up @@ -470,6 +495,14 @@ async def edit(
position or it will fail.
reason: Optional[:class:`str`]
The reason for editing this role. Shows up on the audit log.
primary_color: Union[:class:`Colour`, :class:`int`, None]
The primary color for the role. If provided, must be an integer or :class:`Colour`.
secondary_color: Union[:class:`Colour`, :class:`int`, None]
The secondary color for the role.
tertiary_color: Union[:class:`Colour`, :class:`int`, None]
The tertiary_color color for the role. Used for holographic role.
The holographic preset is:
{"primary_color": 11127295, "secondary_color": 16759788, "tertiary_color": 16761760}

Raises
-------
Expand Down Expand Up @@ -519,6 +552,38 @@ async def edit(
if mentionable is not MISSING:
payload['mentionable'] = mentionable

solid_color_used = color is not MISSING or colour is not MISSING
colors_used = primary_color is not MISSING or secondary_color is not MISSING or tertiary_color is not MISSING
if solid_color_used and colors_used:
raise TypeError(
"You must choose either only solid color (color/colour) or colors (primary_color/secondary_color/tertiary_color), not both."
)

colors_payload: Dict[str, Any] = {}
if primary_color is not MISSING:
if primary_color is None:
colors_payload['primary_color'] = None
elif isinstance(primary_color, int):
colors_payload['primary_color'] = primary_color
else:
colors_payload['primary_color'] = primary_color.value
if secondary_color is not MISSING:
if secondary_color is None:
colors_payload['secondary_color'] = None
elif isinstance(secondary_color, int):
colors_payload['secondary_color'] = secondary_color
else:
colors_payload['secondary_color'] = secondary_color.value
if tertiary_color is not MISSING:
if tertiary_color is None:
colors_payload['tertiary_color'] = None
elif isinstance(tertiary_color, int):
colors_payload['tertiary_color'] = tertiary_color
else:
colors_payload['tertiary_color'] = tertiary_color.value
if colors_payload:
payload['colors'] = colors_payload

data = await self._state.http.edit_role(self.guild.id, self.id, reason=reason, **payload)
return Role(guild=self.guild, data=data, state=self._state)

Expand Down
Loading