From 2502a783cb5b54c1179d7c1f60dc4283f923b98e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=8F=A1=E8=8A=B1=E6=B0=B4=E6=9C=88?= Date: Tue, 8 Jul 2025 00:06:28 -0300 Subject: [PATCH 1/5] Add BCP47 unicode tags for Locale enum Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com> --- discord/enums.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/discord/enums.py b/discord/enums.py index 71f755c12..acc780120 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -21,6 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ + from __future__ import annotations import types @@ -694,6 +695,42 @@ class MFALevel(Enum, comparable=True): require_2fa = 1 +_UNICODE_LANG_MAP: Dict[str, str] = { + 'bg': 'bg-BG', + 'zh-CN': 'zh-CN', + 'zh-TW': 'zh-TW', + 'hr': 'hr-HR', + 'cs': 'cs-CZ', + 'da': 'da-DK', + 'nl': 'nl-NL', + 'en-US': 'en-US', + 'en-GB': 'en-GB', + 'fi': 'fi-FI', + 'fr': 'fr-FR', + 'de': 'de-DE', + 'el': 'el-GR', + 'hi': 'hi-IN', + 'hu': 'hu-HU', + 'id': 'id-ID', + 'it': 'it-IT', + 'ja': 'ja-JP', + 'ko': 'ko-KR', + 'lt': 'lt-LT', + 'no': 'no-NO', + 'pl': 'pl-PL', + 'pt-BR': 'pt-BR', + 'ro': 'ro-RO', + 'ru': 'ru-RU', + 'es-ES': 'es-ES', + 'es-419': 'es-419', + 'sv-SE': 'sv-SE', + 'th': 'th-TH', + 'tr': 'tr-TR', + 'uk': 'uk-UA', + 'vi': 'vi-VN', +} + + class Locale(Enum): american_english = 'en-US' british_english = 'en-GB' @@ -731,6 +768,17 @@ class Locale(Enum): def __str__(self) -> str: return self.value + @property + def language_code(self) -> str: + """:class:`str`: Returns the locale's BCP 47 language code in the format of ``language-COUNTRY``. + + This is derived from a predefined mapping based on Discord's supported locales. + If no mapping exists for the current locale, this returns the raw locale value as a fallback. + + .. versionadded:: 2.6 + """ + return _UNICODE_LANG_MAP.get(self.value, self.value) + E = TypeVar('E', bound='Enum') From cb7300990f656c0964ea48115354f9416e96dcd1 Mon Sep 17 00:00:00 2001 From: Mak <99765898+makerze@users.noreply.github.com> Date: Tue, 8 Jul 2025 04:07:56 +0100 Subject: [PATCH 2/5] Add role parameters to support new gradient and holographic roles Co-authored-by: dolfies Co-authored-by: DA344 <108473820+DA-344@users.noreply.github.com> Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com> --- discord/guild.py | 48 +++++++++++++++++++++++-- discord/http.py | 2 +- discord/role.py | 82 +++++++++++++++++++++++++++++++++++++++--- discord/types/guild.py | 1 + discord/types/role.py | 7 ++++ 5 files changed, 132 insertions(+), 8 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 6b8e8814e..b03dbbea6 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3648,6 +3648,8 @@ class Guild(Hashable): hoist: bool = ..., display_icon: Union[bytes, str] = MISSING, mentionable: bool = ..., + secondary_colour: Optional[Union[Colour, int]] = ..., + tertiary_colour: Optional[Union[Colour, int]] = ..., ) -> Role: ... @@ -3662,6 +3664,8 @@ class Guild(Hashable): hoist: bool = ..., display_icon: Union[bytes, str] = MISSING, mentionable: bool = ..., + secondary_color: Optional[Union[Colour, int]] = ..., + tertiary_color: Optional[Union[Colour, int]] = ..., ) -> Role: ... @@ -3676,6 +3680,10 @@ class Guild(Hashable): display_icon: Union[bytes, str] = MISSING, mentionable: bool = MISSING, reason: Optional[str] = None, + secondary_color: Optional[Union[Colour, int]] = MISSING, + tertiary_color: Optional[Union[Colour, int]] = MISSING, + secondary_colour: Optional[Union[Colour, int]] = MISSING, + tertiary_colour: Optional[Union[Colour, int]] = MISSING, ) -> Role: """|coro| @@ -3695,6 +3703,10 @@ class Guild(Hashable): This function will now raise :exc:`TypeError` instead of ``InvalidArgument``. + .. versionchanged:: 2.6 + The ``colour`` and ``color`` parameters now set the role's primary color. + + Parameters ----------- name: :class:`str` @@ -3704,6 +3716,15 @@ class Guild(Hashable): colour: Union[:class:`Colour`, :class:`int`] The colour for the role. Defaults to :meth:`Colour.default`. This is aliased to ``color`` as well. + secondary_colour: Optional[Union[:class:`Colour`, :class:`int`]] + The secondary colour for the role. + + .. versionadded:: 2.6 + tertiary_colour: Optional[Union[:class:`Colour`, :class:`int`]] + The tertiary colour for the role. Can only be used for the holographic role preset, + which is ``(11127295, 16759788, 16761760)`` + + .. versionadded:: 2.6 hoist: :class:`bool` Indicates if the role should be shown separately in the member list. Defaults to ``False``. @@ -3738,11 +3759,34 @@ class Guild(Hashable): else: fields['permissions'] = '0' + colours: Dict[str, Any] = {} + actual_colour = colour or color or Colour.default() if isinstance(actual_colour, int): - fields['color'] = actual_colour + colours['primary_color'] = actual_colour else: - fields['color'] = actual_colour.value + colours['primary_color'] = actual_colour.value + + actual_secondary_colour = secondary_colour or secondary_color + actual_tertiary_colour = tertiary_colour or tertiary_color + + if actual_secondary_colour is not MISSING: + if actual_secondary_colour is None: + colours['secondary_color'] = None + elif isinstance(actual_secondary_colour, int): + colours['secondary_color'] = actual_secondary_colour + else: + colours['secondary_color'] = actual_secondary_colour.value + + if actual_tertiary_colour is not MISSING: + if actual_tertiary_colour is None: + colours['tertiary_color'] = None + elif isinstance(actual_tertiary_colour, int): + colours['tertiary_color'] = actual_tertiary_colour + else: + colours['tertiary_color'] = actual_tertiary_colour.value + + fields['colors'] = colours if hoist is not MISSING: fields['hoist'] = hoist diff --git a/discord/http.py b/discord/http.py index 71912f71b..02fd1e136 100644 --- a/discord/http.py +++ b/discord/http.py @@ -1897,7 +1897,7 @@ class HTTPClient: 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) diff --git a/discord/role.py b/discord/role.py index d7fe1e08b..acb112519 100644 --- a/discord/role.py +++ b/discord/role.py @@ -222,6 +222,8 @@ class Role(Hashable): 'tags', '_flags', '_state', + '_secondary_colour', + '_tertiary_colour', ) def __init__(self, *, guild: Guild, state: ConnectionState, data: RolePayload): @@ -273,10 +275,11 @@ class Role(Hashable): return not r def _update(self, data: RolePayload): + colors = data.get('colors', {}) self.name: str = data['name'] self._permissions: int = int(data.get('permissions', 0)) self.position: int = data.get('position', 0) - self._colour: int = data.get('color', 0) + self._colour: int = colors.get('primary_color', 0) self.hoist: bool = data.get('hoist', False) self._icon: Optional[str] = data.get('icon') self.unicode_emoji: Optional[str] = data.get('unicode_emoji') @@ -284,6 +287,8 @@ class Role(Hashable): self.mentionable: bool = data.get('mentionable', False) self.tags: Optional[RoleTags] self._flags: int = data.get('flags', 0) + self._secondary_colour = colors.get('secondary_color', None) + self._tertiary_colour = colors.get('tertiary_color', None) try: self.tags = RoleTags(data['tags']) # pyright: ignore[reportTypedDictNotRequiredAccess] @@ -323,6 +328,34 @@ class Role(Hashable): 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 secondary_colour(self) -> Optional[Colour]: + """Optional[:class:`Colour`]: The role's secondary colour. + .. versionadded:: 2.6 + """ + return Colour(self._secondary_colour) if self._secondary_colour is not None else None + + @property + def secondary_color(self) -> Optional[Colour]: + """Optional[:class:`Colour`]: Alias for :attr:`secondary_colour`. + .. versionadded:: 2.6 + """ + return self.secondary_colour + + @property + def tertiary_colour(self) -> Optional[Colour]: + """Optional[:class:`Colour`]: The role's tertiary colour. + .. versionadded:: 2.6 + """ + return Colour(self._tertiary_colour) if self._tertiary_colour is not None else None + + @property + def tertiary_color(self) -> Optional[Colour]: + """Optional[:class:`Colour`]: Alias for :attr:`tertiary_colour`. + .. versionadded:: 2.6 + """ + return self.tertiary_colour + @property def permissions(self) -> Permissions: """:class:`Permissions`: Returns the role's permissions.""" @@ -330,12 +363,12 @@ class Role(Hashable): @property def colour(self) -> Colour: - """:class:`Colour`: Returns the role colour. An alias exists under ``color``.""" + """:class:`Colour`: Returns the role's primary colour. An alias exists under ``color``.""" return Colour(self._colour) @property def color(self) -> Colour: - """:class:`Colour`: Returns the role color. An alias exists under ``colour``.""" + """:class:`Colour`: Returns the role's primary colour. An alias exists under ``colour``.""" return self.colour @property @@ -425,6 +458,10 @@ class Role(Hashable): mentionable: bool = MISSING, position: int = MISSING, reason: Optional[str] = MISSING, + secondary_color: Optional[Union[Colour, int]] = MISSING, + tertiary_color: Optional[Union[Colour, int]] = MISSING, + secondary_colour: Optional[Union[Colour, int]] = MISSING, + tertiary_colour: Optional[Union[Colour, int]] = MISSING, ) -> Optional[Role]: """|coro| @@ -447,6 +484,9 @@ class Role(Hashable): This function will now raise :exc:`ValueError` instead of ``InvalidArgument``. + .. versionchanged:: 2.6 + The ``colour`` and ``color`` parameters now set the role's primary color. + Parameters ----------- name: :class:`str` @@ -455,6 +495,15 @@ class Role(Hashable): The new permissions to change to. colour: Union[:class:`Colour`, :class:`int`] The new colour to change to. (aliased to color as well) + secondary_colour: Optional[Union[:class:`Colour`, :class:`int`]] + The new secondary colour for the role. + + .. versionadded:: 2.6 + tertiary_colour: Optional[Union[:class:`Colour`, :class:`int`]] + The new tertiary colour for the role. Can only be used for the holographic role preset, + which is ``(11127295, 16759788, 16761760)`` + + .. versionadded:: 2.6 hoist: :class:`bool` Indicates if the role should be shown separately in the member list. display_icon: Optional[Union[:class:`bytes`, :class:`str`]] @@ -490,14 +539,17 @@ class Role(Hashable): await self._move(position, reason=reason) payload: Dict[str, Any] = {} + + colours: Dict[str, Any] = {} + if color is not MISSING: colour = color if colour is not MISSING: if isinstance(colour, int): - payload['color'] = colour + colours['primary_color'] = colour else: - payload['color'] = colour.value + colours['primary_color'] = colour.value if name is not MISSING: payload['name'] = name @@ -519,6 +571,26 @@ class Role(Hashable): if mentionable is not MISSING: payload['mentionable'] = mentionable + actual_secondary_colour = secondary_colour or secondary_color + actual_tertiary_colour = tertiary_colour or tertiary_color + + if actual_secondary_colour is not MISSING: + if actual_secondary_colour is None: + colours['secondary_color'] = None + elif isinstance(actual_secondary_colour, int): + colours['secondary_color'] = actual_secondary_colour + else: + colours['secondary_color'] = actual_secondary_colour.value + if actual_tertiary_colour is not MISSING: + if actual_tertiary_colour is None: + colours['tertiary_color'] = None + elif isinstance(actual_tertiary_colour, int): + colours['tertiary_color'] = actual_tertiary_colour + else: + colours['tertiary_color'] = actual_tertiary_colour.value + + if colours: + payload['colors'] = colours 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) diff --git a/discord/types/guild.py b/discord/types/guild.py index 7ac90b89e..0e328fed2 100644 --- a/discord/types/guild.py +++ b/discord/types/guild.py @@ -90,6 +90,7 @@ GuildFeature = Literal[ 'VERIFIED', 'VIP_REGIONS', 'WELCOME_SCREEN_ENABLED', + 'ENHANCED_ROLE_COLORS', 'RAID_ALERTS_DISABLED', 'SOUNDBOARD', 'MORE_SOUNDBOARD', diff --git a/discord/types/role.py b/discord/types/role.py index d32de8803..dabd1c1cf 100644 --- a/discord/types/role.py +++ b/discord/types/role.py @@ -30,10 +30,17 @@ from typing_extensions import NotRequired from .snowflake import Snowflake +class RoleColours(TypedDict): + primary_color: int + secondary_color: Optional[int] + tertiary_color: Optional[int] + + class Role(TypedDict): id: Snowflake name: str color: int + colors: RoleColours hoist: bool position: int permissions: str From 66922cc2d15417d2ce900f04987c2f361537ac6d Mon Sep 17 00:00:00 2001 From: DA344 <108473820+DA-344@users.noreply.github.com> Date: Wed, 9 Jul 2025 03:15:07 +0200 Subject: [PATCH 3/5] Fix documentation on Role secondary and tertiary colours Fix .. versionadded:: strings on Role.secondary_ and Role.tertiary_ colours --- discord/role.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/discord/role.py b/discord/role.py index acb112519..18b024059 100644 --- a/discord/role.py +++ b/discord/role.py @@ -331,6 +331,7 @@ class Role(Hashable): @property def secondary_colour(self) -> Optional[Colour]: """Optional[:class:`Colour`]: The role's secondary colour. + .. versionadded:: 2.6 """ return Colour(self._secondary_colour) if self._secondary_colour is not None else None @@ -338,6 +339,7 @@ class Role(Hashable): @property def secondary_color(self) -> Optional[Colour]: """Optional[:class:`Colour`]: Alias for :attr:`secondary_colour`. + .. versionadded:: 2.6 """ return self.secondary_colour @@ -345,6 +347,7 @@ class Role(Hashable): @property def tertiary_colour(self) -> Optional[Colour]: """Optional[:class:`Colour`]: The role's tertiary colour. + .. versionadded:: 2.6 """ return Colour(self._tertiary_colour) if self._tertiary_colour is not None else None @@ -352,6 +355,7 @@ class Role(Hashable): @property def tertiary_color(self) -> Optional[Colour]: """Optional[:class:`Colour`]: Alias for :attr:`tertiary_colour`. + .. versionadded:: 2.6 """ return self.tertiary_colour From b1be7dea7445f3b6e8a86d210897c796cc4389e7 Mon Sep 17 00:00:00 2001 From: El Laggron Date: Wed, 9 Jul 2025 03:16:39 +0200 Subject: [PATCH 4/5] Handle empty guild_ids list for app_commands --- discord/app_commands/commands.py | 17 ++++++++++++----- discord/ext/commands/hybrid.py | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/discord/app_commands/commands.py b/discord/app_commands/commands.py index d5b8d93b2..1496a82bb 100644 --- a/discord/app_commands/commands.py +++ b/discord/app_commands/commands.py @@ -686,9 +686,9 @@ class Command(Generic[GroupT, P, T]): self._params: Dict[str, CommandParameter] = _extract_parameters_from_callback(callback, callback.__globals__) self.checks: List[Check] = getattr(callback, '__discord_app_commands_checks__', []) - self._guild_ids: Optional[List[int]] = guild_ids or getattr( - callback, '__discord_app_commands_default_guilds__', None - ) + self._guild_ids: Optional[List[int]] = guild_ids + if self._guild_ids is None: + self._guild_ids = getattr(callback, '__discord_app_commands_default_guilds__', None) self.default_permissions: Optional[Permissions] = getattr( callback, '__discord_app_commands_default_permissions__', None ) @@ -1249,7 +1249,9 @@ class ContextMenu: self._param_name = param self._annotation = annotation self.module: Optional[str] = callback.__module__ - self._guild_ids = guild_ids or getattr(callback, '__discord_app_commands_default_guilds__', None) + self._guild_ids = guild_ids + if self._guild_ids is None: + self._guild_ids = getattr(callback, '__discord_app_commands_default_guilds__', None) self.on_error: Optional[UnboundError] = None self.default_permissions: Optional[Permissions] = getattr( callback, '__discord_app_commands_default_permissions__', None @@ -1586,7 +1588,9 @@ class Group: self._attr: Optional[str] = None self._owner_cls: Optional[Type[Any]] = None - self._guild_ids: Optional[List[int]] = guild_ids or getattr(cls, '__discord_app_commands_default_guilds__', None) + self._guild_ids: Optional[List[int]] = guild_ids + if self._guild_ids is None: + self._guild_ids = getattr(cls, '__discord_app_commands_default_guilds__', None) if default_permissions is MISSING: if cls.__discord_app_commands_default_permissions__ is MISSING: @@ -2366,6 +2370,9 @@ def guilds(*guild_ids: Union[Snowflake, int]) -> Callable[[T], T]: specified by this decorator become the default guilds that it's added to rather than being a global command. + If no arguments are given, then the command will not be synced anywhere. This may + be modified later using the :meth:`CommandTree.add_command` method. + .. note:: Due to an implementation quirk and Python limitation, if this is used in conjunction diff --git a/discord/ext/commands/hybrid.py b/discord/ext/commands/hybrid.py index 0857003fa..99b537ca1 100644 --- a/discord/ext/commands/hybrid.py +++ b/discord/ext/commands/hybrid.py @@ -656,9 +656,9 @@ class HybridGroup(Group[CogT, P, T]): self.fallback_locale: Optional[app_commands.locale_str] = fallback_locale if self.with_app_command: - guild_ids = attrs.pop('guild_ids', None) or getattr( - self.callback, '__discord_app_commands_default_guilds__', None - ) + guild_ids = attrs.pop('guild_ids', None) + if guild_ids is None: + guild_ids = getattr(self.callback, '__discord_app_commands_default_guilds__', None) guild_only = getattr(self.callback, '__discord_app_commands_guild_only__', False) default_permissions = getattr(self.callback, '__discord_app_commands_default_permissions__', None) nsfw = getattr(self.callback, '__discord_app_commands_is_nsfw__', False) From a00510988a204517f4777f1231407de3db726ae5 Mon Sep 17 00:00:00 2001 From: z03h <7235242+z03h@users.noreply.github.com> Date: Wed, 9 Jul 2025 13:56:38 -0400 Subject: [PATCH 5/5] Support new role colours in audit log --- discord/audit_logs.py | 18 +++++++++++++++++- discord/types/audit_log.py | 9 ++++++++- docs/api.rst | 34 +++++++++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/discord/audit_logs.py b/discord/audit_logs.py index 89577769f..b781dcf80 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -69,7 +69,7 @@ if TYPE_CHECKING: DefaultReaction as DefaultReactionPayload, ) from .types.invite import Invite as InvitePayload - from .types.role import Role as RolePayload + from .types.role import Role as RolePayload, RoleColours from .types.snowflake import Snowflake from .types.command import ApplicationCommandPermissions from .types.automod import AutoModerationAction @@ -407,6 +407,12 @@ class AuditLogChanges: self._handle_trigger_attr_update(self.after, self.before, entry, trigger_attr, elem['new_value']) # type: ignore continue + # special case for colors to set secondary and tertiary colos/colour attributes + if attr == 'colors': + self._handle_colours(self.before, elem['old_value']) # type: ignore # should be a RoleColours dict + self._handle_colours(self.after, elem['new_value']) # type: ignore # should be a RoleColours dict + continue + try: key, transformer = self.TRANSFORMERS[attr] except (ValueError, KeyError): @@ -539,6 +545,16 @@ class AuditLogChanges: except (AttributeError, TypeError): pass + def _handle_colours(self, diff: AuditLogDiff, colours: RoleColours): + # handle colours to multiple colour attributes + diff.color = diff.colour = Colour(colours['primary_color']) + + secondary_colour = colours['secondary_color'] + tertiary_colour = colours['tertiary_color'] + + diff.secondary_color = diff.secondary_colour = Colour(secondary_colour) if secondary_colour is not None else None + diff.tertiary_color = diff.tertiary_colour = Colour(tertiary_colour) if tertiary_colour is not None else None + def _create_trigger(self, diff: AuditLogDiff, entry: AuditLogEntry) -> AutoModTrigger: # check if trigger has already been created if not hasattr(diff, 'trigger'): diff --git a/discord/types/audit_log.py b/discord/types/audit_log.py index 2c37542fd..c9d305695 100644 --- a/discord/types/audit_log.py +++ b/discord/types/audit_log.py @@ -33,7 +33,7 @@ from .integration import IntegrationExpireBehavior, PartialIntegration from .user import User from .scheduled_event import EntityType, EventStatus, GuildScheduledEvent from .snowflake import Snowflake -from .role import Role +from .role import Role, RoleColours from .channel import ChannelType, DefaultReaction, PrivacyLevel, VideoQualityMode, PermissionOverwrite, ForumTag from .threads import Thread from .command import ApplicationCommand, ApplicationCommandPermissions @@ -297,6 +297,12 @@ class _AuditLogChange_TriggerMetadata(TypedDict): old_value: Optional[AutoModerationTriggerMetadata] +class _AuditLogChange_RoleColours(TypedDict): + key: Literal['colors'] + new_value: RoleColours + old_value: RoleColours + + AuditLogChange = Union[ _AuditLogChange_Str, _AuditLogChange_AssetHash, @@ -321,6 +327,7 @@ AuditLogChange = Union[ _AuditLogChange_AvailableTags, _AuditLogChange_DefaultReactionEmoji, _AuditLogChange_TriggerMetadata, + _AuditLogChange_RoleColours, ] diff --git a/docs/api.rst b/docs/api.rst index dc6775ec6..c7d9e351f 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -927,25 +927,25 @@ Members .. function:: on_raw_presence_update(payload) Called when a :class:`Member` updates their presence. - + This requires :attr:`Intents.presences` to be enabled. - Unlike :func:`on_presence_update`, when enabled, this is called regardless of the state of internal guild + Unlike :func:`on_presence_update`, when enabled, this is called regardless of the state of internal guild and member caches, and **does not** provide a comparison between the previous and updated states of the :class:`Member`. .. important:: - By default, this event is only dispatched when :attr:`Intents.presences` is enabled **and** :attr:`Intents.members` + By default, this event is only dispatched when :attr:`Intents.presences` is enabled **and** :attr:`Intents.members` is disabled. You can manually override this behaviour by setting the **enable_raw_presences** flag in the :class:`Client`, however :attr:`Intents.presences` is always required for this event to work. - + .. versionadded:: 2.5 :param payload: The raw presence update event model. :type payload: :class:`RawPresenceUpdateEvent` - + Messages ~~~~~~~~~ @@ -2456,6 +2456,8 @@ of :class:`enum.Enum`. Possible attributes for :class:`AuditLogDiff`: - :attr:`~AuditLogDiff.colour` + - :attr:`~AuditLogDiff.secondary_colour` + - :attr:`~AuditLogDiff.tertiary_colour` - :attr:`~AuditLogDiff.mentionable` - :attr:`~AuditLogDiff.hoist` - :attr:`~AuditLogDiff.icon` @@ -2479,6 +2481,8 @@ of :class:`enum.Enum`. Possible attributes for :class:`AuditLogDiff`: - :attr:`~AuditLogDiff.colour` + - :attr:`~AuditLogDiff.secondary_colour` + - :attr:`~AuditLogDiff.tertiary_colour` - :attr:`~AuditLogDiff.mentionable` - :attr:`~AuditLogDiff.hoist` - :attr:`~AuditLogDiff.icon` @@ -2496,6 +2500,8 @@ of :class:`enum.Enum`. Possible attributes for :class:`AuditLogDiff`: - :attr:`~AuditLogDiff.colour` + - :attr:`~AuditLogDiff.secondary_colour` + - :attr:`~AuditLogDiff.tertiary_colour` - :attr:`~AuditLogDiff.mentionable` - :attr:`~AuditLogDiff.hoist` - :attr:`~AuditLogDiff.name` @@ -4210,6 +4216,24 @@ AuditLogDiff :type: :class:`Colour` + .. attribute:: secondary_colour + secondary_color + + The secondary colour of a role. + + See also :attr:`Role.secondary_colour` + + :type: Optional[:class:`Colour`] + + .. attribute:: tertiary_colour + tertiary_color + + The tertiary colour of a role. + + See also :attr:`Role.tertiary_colour` + + :type: Optional[:class:`Colour`] + .. attribute:: hoist Whether the role is being hoisted or not.