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

Copy Markdown View Source

Represents a Discord guild member.

Summary

Functions

Adds a role to a guild member.

Applies a changeset to a member. No-op if the changeset has no changes.

Adds a change to an existing changeset for this entity.

Creates a changeset for batching mutations to this entity.

Fetches a member by guild ID and user ID. Checks cache first, falls back to REST.

Kicks a member from a guild.

Modifies the bot's own member in a guild — its per-guild profile.

Removes a role from a guild member.

When the member's timeout ends, or nil if they have never been timed out.

Returns true while the member is currently timed out.

The member's highest role in a guild, as the cached role map, or nil when they have none beyond @everyone (or their roles are not cached).

The position of the member's highest role in a guild; 0, the position of @everyone, when they have no other role. Compare two members, or a member and a role, to know which one ranks above the other — Discord refuses to let a member act on someone at or above them.

Types

t()

@type t() :: %EDA.Member{
  avatar: String.t() | nil,
  banner: String.t() | nil,
  bio: String.t() | nil,
  communication_disabled_until: String.t() | nil,
  deaf: boolean() | nil,
  joined_at: String.t() | nil,
  mute: boolean() | nil,
  nick: String.t() | nil,
  pending: boolean() | nil,
  permissions: String.t() | nil,
  premium_since: String.t() | nil,
  roles: [String.t()] | nil,
  user: EDA.User.t() | nil
}

Functions

add_role(guild_id, member, role_id, opts \\ [])

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

Adds a role to a guild member.

Options

  • :reason - Audit log reason

apply_changeset(guild_id, changeset, opts \\ [])

@spec apply_changeset(String.t() | integer(), EDA.Entity.Changeset.t(), keyword()) ::
  {:ok, t()} | {:error, term()}

Applies a changeset to a member. No-op if the changeset has no changes.

Requires guild_id since members are guild-scoped.

Options

  • :reason - Audit log reason

change(cs, key, value)

Adds a change to an existing changeset for this entity.

changeset(entity)

@spec changeset(t()) :: EDA.Entity.Changeset.t()

Creates a changeset for batching mutations to this entity.

fetch_member(guild_id, user_id)

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

Fetches a member by guild ID and user ID. Checks cache first, falls back to REST.

from_raw(raw)

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

kick(guild_id, member, opts \\ [])

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

Kicks a member from a guild.

Options

  • :reason - Audit log reason

modify(guild_id, member, payload, opts \\ [])

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

Modifies a guild member.

Options

  • :reason - Audit log reason

modify_me(guild_id, opts \\ [])

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

Modifies the bot's own member in a guild — its per-guild profile.

Returns a t/0. Takes the same options as EDA.API.Member.modify_me/2: :nick, :avatar, :banner, :bio and :reason. :avatar and :banner accept a path, raw image bytes or a data URI, and nil clears the field so the account-wide value shows again.

Only :nick needs a permission (CHANGE_NICKNAME); the appearance fields need none.

EDA.Member.modify_me(guild_id, nick: "EDA", avatar: "priv/avatar.png")

Fields you leave out are untouched, so setting a bio alone keeps the avatar and banner.

:bio comes back on this response but not on a later fetch_member/2: Discord omits it from the guild member object. Read it from the struct this returns, or keep your own copy — a round trip will not give it back.

remove_role(guild_id, member, role_id, opts \\ [])

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

Removes a role from a guild member.

Options

  • :reason - Audit log reason

time_out_end(member)

@spec time_out_end(t() | map()) :: DateTime.t() | nil

When the member's timeout ends, or nil if they have never been timed out.

May return a date in the past, in which case the timeout has expired — Discord leaves the field populated. Use timed_out?/1 to ask whether it is currently active. JDA draws the same distinction with getTimeOutEnd() / isTimedOut().

Accepts a struct or a raw member map.

Examples

iex> EDA.Member.time_out_end(%EDA.Member{communication_disabled_until: "2099-01-01T00:00:00Z"})
~U[2099-01-01 00:00:00Z]

iex> EDA.Member.time_out_end(%EDA.Member{})
nil

timed_out?(member)

@spec timed_out?(t() | map()) :: boolean()

Returns true while the member is currently timed out.

Accepts a struct or a raw member map.

Not reflected in permissions

Discord removes every permission except VIEW_CHANNEL and READ_MESSAGE_HISTORY from a timed-out member, but EDA.Permission.in_channel/3 does not account for it — neither does JDA's hasPermission. Check this yourself before gating an action on a permission.

Examples

iex> EDA.Member.timed_out?(%EDA.Member{communication_disabled_until: "2099-01-01T00:00:00Z"})
true

iex> EDA.Member.timed_out?(%EDA.Member{communication_disabled_until: "2020-01-01T00:00:00Z"})
false

iex> EDA.Member.timed_out?(%EDA.Member{})
false

top_role(member, guild_id)

@spec top_role(t() | map(), String.t() | integer()) :: map() | nil

The member's highest role in a guild, as the cached role map, or nil when they have none beyond @everyone (or their roles are not cached).

"Highest" is the role with the greatest position, ties broken by the lower id, which is how Discord orders roles in the member list and in permission hierarchy checks.

top_role_position(member, guild_id)

@spec top_role_position(t() | map(), String.t() | integer()) :: non_neg_integer()

The position of the member's highest role in a guild; 0, the position of @everyone, when they have no other role. Compare two members, or a member and a role, to know which one ranks above the other — Discord refuses to let a member act on someone at or above them.