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 a guild member.
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
@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
@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
@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
@spec change(EDA.Entity.Changeset.t(), atom(), term()) :: EDA.Entity.Changeset.t()
Adds a change to an existing changeset for this entity.
@spec changeset(t()) :: EDA.Entity.Changeset.t()
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.
@spec kick(String.t() | integer(), t() | String.t() | integer(), keyword()) :: :ok | {:error, term()}
Kicks a member from a guild.
Options
:reason- Audit log reason
@spec modify(String.t() | integer(), t() | String.t() | integer(), map(), keyword()) :: {:ok, t()} | {:error, term()}
Modifies a guild member.
Options
:reason- Audit log reason
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.
@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
@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
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
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.
@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.