EDA.Onboarding (EDA v0.5.0-beta.2)

Copy Markdown View Source

A guild's onboarding: the questions new members answer, and the channels they join by default.

{:ok, onboarding} = EDA.Onboarding.fetch(guild_id)

onboarding
|> EDA.Onboarding.add_prompt(
  EDA.Onboarding.prompt("What brings you here?", [
    EDA.Onboarding.option("Gaming", emoji: "🎮", role_ids: [gamer_role]),
    EDA.Onboarding.option("Art", emoji: "🎨", channel_ids: [art_channel])
  ])
)
|> EDA.Onboarding.save(reason: "New question")

Saving replaces everything

Discord's endpoint is a PUT: the prompts sent become the whole list, and a prompt left out is deleted. So change onboarding by fetching it, editing the struct, and saving it back — save/2 sends every prompt it holds.

That round trip hides a trap this module takes care of. Discord returns an option's emoji as an emoji object but only accepts it as emoji_id, emoji_name and emoji_animated; sending back what was read clears every emoji. to_payload/1 converts them.

New prompts and options need an id in the request although Discord assigns its own on save. prompt/3 and option/2 fill in a placeholder; the saved onboarding carries Discord's ids.

Enabling

Saving with enabled: true needs the guild to meet Discord's constraints: at least 7 default channels, 5 of which @everyone can send messages in. mode: :advanced counts the questions' channels towards them as well. Onboarding requires MANAGE_GUILD and MANAGE_ROLES.

Summary

Functions

Appends a prompt.

Fetches a guild's onboarding.

Converts a raw onboarding object into this struct.

Builds a new option for a prompt.

Builds a new prompt.

Removes the prompt with this id.

Saves the whole onboarding — every prompt it holds — and returns it as Discord stored it.

The request body save/2 sends: every prompt, with option emojis in the flat form Discord accepts, and the mode as its integer.

Types

mode()

@type mode() :: :default | :advanced

t()

@type t() :: %EDA.Onboarding{
  default_channel_ids: [String.t()],
  enabled: boolean(),
  guild_id: String.t() | nil,
  mode: mode() | integer(),
  prompts: [EDA.Onboarding.Prompt.t()]
}

Functions

add_prompt(onboarding, prompt)

@spec add_prompt(t(), EDA.Onboarding.Prompt.t()) :: t()

Appends a prompt.

fetch(guild_id)

@spec fetch(String.t() | integer()) :: {:ok, t()} | {:error, term()}

Fetches a guild's onboarding.

from_raw(raw)

@spec from_raw(map()) :: t()

Converts a raw onboarding object into this struct.

option(title, opts \\ [])

@spec option(
  String.t(),
  keyword()
) :: EDA.Onboarding.Option.t()

Builds a new option for a prompt.

Options

  • :description
  • :emoji — a unicode emoji as a string, or an EDA.Emoji struct for a custom one
  • :channel_ids — channels a member joins by picking this option
  • :role_ids — roles a member gets by picking it
  • :id — the option's id, to replace an existing option; a placeholder otherwise

An option should grant at least one channel or role; Discord refuses one that does neither.

prompt(title, options, opts \\ [])

Builds a new prompt.

Options

  • :type — :multiple_choice (default) or :dropdown
  • :single_select — members may pick only one option (default false)
  • :required — members must answer before finishing onboarding (default false)
  • :in_onboarding — shown during onboarding; false shows it only under Channels & Roles (default true)
  • :id — the prompt's id, to replace an existing prompt; a placeholder otherwise

remove_prompt(onboarding, prompt_id)

@spec remove_prompt(t(), String.t()) :: t()

Removes the prompt with this id.

save(onboarding, opts \\ [])

@spec save(
  t(),
  keyword()
) :: {:ok, t()} | {:error, term()}

Saves the whole onboarding — every prompt it holds — and returns it as Discord stored it.

Options

  • :reason — audit log reason

to_payload(onboarding)

@spec to_payload(t()) :: map()

The request body save/2 sends: every prompt, with option emojis in the flat form Discord accepts, and the mode as its integer.

iex> onboarding = %EDA.Onboarding{
...>   prompts: [EDA.Onboarding.prompt("Q", [%EDA.Onboarding.Option{id: "5", title: "A", emoji: %EDA.Emoji{id: "9", name: "party", animated: true}}], id: "4")],
...>   default_channel_ids: ["1"]
...> }
iex> body = EDA.Onboarding.to_payload(onboarding)
iex> hd(hd(body.prompts).options) |> Map.take([:emoji_id, :emoji_name, :emoji_animated])
%{emoji_id: "9", emoji_name: "party", emoji_animated: true}