# SPDX-License-Identifier: MIT from __future__ import annotations from typing import TYPE_CHECKING, FrozenSet, List, Optional, Union from .enums import OnboardingPromptType, try_enum from .mixins import Hashable if TYPE_CHECKING: from .emoji import Emoji, PartialEmoji from .guild import Guild, GuildChannel from .role import Role from .types.onboarding import ( Onboarding as OnboardingPayload, OnboardingPrompt as OnboardingPromptPayload, OnboardingPromptOption as OnboardingPromptOptionPayload, ) __all__ = ( "Onboarding", "OnboardingPrompt", "OnboardingPromptOption", ) class Onboarding: """Represents a guild onboarding object. .. versionadded:: 2.9 Attributes ---------- guild: :class:`Guild` The guild this onboarding is part of. prompts: List[:class:`OnboardingPrompt`] The prompts shown during onboarding and in community customization. enabled: :class:`bool` Whether onboarding is enabled. default_channel_ids: FrozenSet[:class:`int`] The IDs of the channels that will be shown to new members by default. """ __slots__ = ( "guild", "prompts", "enabled", "default_channel_ids", ) def __init__(self, *, guild: Guild, data: OnboardingPayload) -> None: self.guild: Guild = guild self._from_data(data) def _from_data(self, data: OnboardingPayload) -> None: self.prompts: List[OnboardingPrompt] = [ OnboardingPrompt(data=prompt, guild=self.guild) for prompt in data["prompts"] ] self.enabled: bool = data["enabled"] self.default_channel_ids: FrozenSet[int] = ( frozenset(map(int, exempt_channels)) if (exempt_channels := data["default_channel_ids"]) else frozenset() ) def __repr__(self) -> str: return ( f"" ) @property def default_channels(self) -> List[GuildChannel]: """List[:class:`abc.GuildChannel`]: The list of channels that will be shown to new members by default.""" return list(filter(None, map(self.guild.get_channel, self.default_channel_ids))) class OnboardingPrompt(Hashable): """Represents an onboarding prompt. .. versionadded:: 2.9 Attributes ---------- id: :class:`int` The onboarding prompt's ID. type: :class:`OnboardingPromptType` The onboarding prompt's type. options: List[:class:`OnboardingPromptOption`] The onboarding prompt's options. title: :class:`str` The onboarding prompt's title. single_select: :class:`bool` Whether users are limited to selecting one option for the prompt. required: :class:`bool` Whether the prompt is required before a user completes the onboarding flow. in_onboarding: :class:`bool` Whether the prompt is present in the onboarding flow. If ``False``, the prompt will only appear in community customization. """ __slots__ = ( "guild", "id", "title", "options", "single_select", "required", "in_onboarding", "type", ) def __init__(self, *, guild: Guild, data: OnboardingPromptPayload) -> None: self.guild = guild self.id: int = int(data["id"]) self.title: str = data["title"] self.options: List[OnboardingPromptOption] = [ OnboardingPromptOption(data=option, guild=guild) for option in data["options"] ] self.single_select: bool = data["single_select"] self.required: bool = data["required"] self.in_onboarding: bool = data["in_onboarding"] self.type: OnboardingPromptType = try_enum(OnboardingPromptType, data["type"]) def __str__(self) -> str: return self.title def __repr__(self) -> str: return ( f"" ) class OnboardingPromptOption(Hashable): """Represents an onboarding prompt option. .. versionadded:: 2.9 Attributes ---------- id: :class:`int` The prompt option's ID. emoji: Optional[Union[:class:`PartialEmoji`, :class:`Emoji`, :class:`str`]] The prompt option's emoji. title: :class:`str` The prompt option's title. description: Optional[:class:`str`] The prompt option's description. role_ids: FrozenSet[:class:`int`] The IDs of the roles that will be added to the user when they select this option. channel_ids: FrozenSet[:class:`int`] The IDs of the channels that the user will see when they select this option. """ __slots__ = ("id", "title", "description", "emoji", "guild", "role_ids", "channel_ids") def __init__(self, *, guild: Guild, data: OnboardingPromptOptionPayload) -> None: self.guild: Guild = guild self.id: int = int(data["id"]) self.title: str = data["title"] self.description: Optional[str] = data["description"] self.role_ids: FrozenSet[int] = ( frozenset(map(int, roles_ids)) if (roles_ids := data.get("role_ids")) else frozenset() ) self.channel_ids: FrozenSet[int] = ( frozenset(map(int, channels_ids)) if (channels_ids := data.get("channel_ids")) else frozenset() ) self.emoji: Optional[Union[Emoji, PartialEmoji, str]] if emoji_data := data.get("emoji"): self.emoji = guild._state.get_reaction_emoji(emoji_data) else: self.emoji = None def __str__(self) -> str: return self.title def __repr__(self) -> str: return ( f"" ) @property def roles(self) -> List[Role]: """List[:class:`Role`]: A list of roles that will be added to the user when they select this option.""" return list(filter(None, map(self.guild.get_role, self.role_ids))) @property def channels(self) -> List[GuildChannel]: """List[:class:`abc.GuildChannel`]: A list of channels that the user will see when they select this option.""" return list(filter(None, map(self.guild.get_channel, self.channel_ids)))