Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions lib/nostrum/api/guild.ex
Original file line number Diff line number Diff line change
Expand Up @@ -846,30 +846,23 @@ defmodule Nostrum.Api.Guild do
Nostrum.Api.Guild.modify_member(41771983423143937, 637162356451, nick: "Nostrum")
{:ok, %Nostrum.Struct.Member{}}
```

```elixir
Nostrum.Api.Guild.modify_member(41771983423143937, :me, nick: "Nostrum")
{:ok, %Nostrum.Struct.Member{}}
```
"""
@spec modify_member(Guild.id(), User.id() | :me, Api.options(), AuditLogEntry.reason()) ::
@spec modify_member(Guild.id(), User.id(), Api.options(), AuditLogEntry.reason()) ::

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks to now be undoing some of your latest changes to master around the @me endpoint support, I assume this is unintentional and should get reverted.

@lara-rium lara-rium Mar 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my thinking was that this pr is solely for decoding message flags so other features i added should be reverted. this conflict should probably be fixed while merging #717 or this pr. this wouldnt have happened if i hadnt forgotten to create a sole branch for #717 but it is what it is. lmk if u dont agree w this revert

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be best if you could drop these unrelated commits from the history of this branch, could you do that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, how do i do that?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the basic idea would be something like this:

  1. Start by making a backup of your branch: git checkout -b message-flags-backup, then git checkout message-flags
  2. git rebase -i master
  3. Do a local sanity check. If it's bad, git reset --hard message-flags-backup
  4. git push -f

But I'm really struggling to see which commit actually intoduces the message flag decoding without other changes. It would maybe be best if you open a new pull request with only the message flag changes cherry picked out of here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i unfortunately don't have time for this right now.. anyone else is welcome to take this on

Api.error() | {:ok, Member.t()}
def modify_member(guild_id, user_id, options \\ %{}, reason \\ nil)

def modify_member(guild_id, user_id, options, reason) when is_list(options),
do: modify_member(guild_id, user_id, Map.new(options), reason)

def modify_member(guild_id, user_id, %{} = options, reason)
when is_snowflake(guild_id) and (is_snowflake(user_id) or user_id == :me) do
when is_snowflake(guild_id) and is_snowflake(user_id) do
options =
options
|> Helpers.maybe_convert_date_time(:communication_disabled_until)

user = if user_id == :me, do: "@me", else: user_id

Api.request(%{
method: :patch,
route: Constants.guild_member(guild_id, user),
route: Constants.guild_member(guild_id, user_id),
body: options,
params: [],
headers: Helpers.maybe_add_reason(reason)
Expand Down
12 changes: 12 additions & 0 deletions lib/nostrum/struct/message.ex
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,18 @@ defmodule Nostrum.Struct.Message do
if the message is a response to an interaction, this is the ID of the interaction's application
"""
@type application_id :: Application.id() | nil

@typedoc """
Message flags combined as a bitfield.

`nil` when no flags are set.

To convert the raw integer bitfield into a struct of flag values, use
`Nostrum.Struct.Message.Flags.from_integer/1`.
"""
Comment thread
lara-rium marked this conversation as resolved.
@typedoc since: "NEXTVERSION"
@type flags :: Flags.raw_flags() | nil
Comment thread
lara-rium marked this conversation as resolved.

@typedoc """
Partial Guild Member object received with the Message Create event if message came from a guild channel
"""
Expand Down
198 changes: 198 additions & 0 deletions lib/nostrum/struct/message/flags.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
defmodule Nostrum.Struct.Message.Flags do
@moduledoc """
Struct representing the flags a message can have
"""
Comment thread
lara-rium marked this conversation as resolved.
@moduledoc since: "NEXTVERSION"

import Bitwise

defstruct crossposted: false,
is_crosspost: false,
suppress_embeds: false,
source_message_deleted: false,
urgent: false,
has_thread: false,
ephemeral: false,
loading: false,
failed_to_mention_some_roles_in_thread: false,
suppress_notifications: false,
is_voice_message: false,
has_snapshot: false,
is_components_v2: false

@typedoc """
Message has been published to subscribed channels (via Channel Following)
"""
@type crossposted :: boolean

@typedoc """
Message originated from a message in another channel (via Channel Following)
"""
@type is_crosspost :: boolean

@typedoc """
Do not include any embeds when serializing message
"""
@type suppress_embeds :: boolean

@typedoc """
The source message for a crosspost has been deleted (via Channel Following)
"""
@type source_message_deleted :: boolean

@typedoc """
Message came from the urgent message system
"""
@type urgent :: boolean

@typedoc """
Message has an associated thread, with the same id as the message
"""
@type has_thread :: boolean

@typedoc """
Message is only visible to the user who invoked the Interaction
"""
@type ephemeral :: boolean

@typedoc """
Message is an Interaction Response and the bot is "thinking"
"""
@type loading :: boolean

@typedoc """
Message failed to mention some roles and add their members to the thread
"""
@type failed_to_mention_some_roles_in_thread :: boolean

@typedoc """
Message will not trigger push and desktop notifications
"""
@type suppress_notifications :: boolean

@typedoc """
Message is a voice message
"""
@type is_voice_message :: boolean

@typedoc """
Message has a snapshot (via Message Forwarding)
"""
@type has_snapshot :: boolean

@typedoc """
Message uses components v2
"""
@type is_components_v2 :: boolean

@type flags :: %__MODULE__{
crossposted: crossposted,
is_crosspost: is_crosspost,
suppress_embeds: suppress_embeds,
source_message_deleted: source_message_deleted,
urgent: urgent,
has_thread: has_thread,
ephemeral: ephemeral,
loading: loading,
failed_to_mention_some_roles_in_thread: failed_to_mention_some_roles_in_thread,
suppress_notifications: suppress_notifications,
is_voice_message: is_voice_message,
has_snapshot: has_snapshot,
is_components_v2: is_components_v2
}

@type t :: flags

@typedoc "Raw message flags as sent by the Discord API"
@type raw_flags :: integer()

@flag_values [
crossposted: 1 <<< 0,
is_crosspost: 1 <<< 1,
suppress_embeds: 1 <<< 2,
source_message_deleted: 1 <<< 3,
urgent: 1 <<< 4,
has_thread: 1 <<< 5,
ephemeral: 1 <<< 6,
loading: 1 <<< 7,
failed_to_mention_some_roles_in_thread: 1 <<< 8,
suppress_notifications: 1 <<< 12,
is_voice_message: 1 <<< 13,
has_snapshot: 1 <<< 14,
is_components_v2: 1 <<< 15
]

@doc """
Constructs a flag struct based on an integer from the Discord API.

## Examples

```elixir
iex> Nostrum.Struct.Message.Flags.from_integer(258)
%Nostrum.Struct.Message.Flags{
crossposted: false,
is_crosspost: true,
suppress_embeds: false,
source_message_deleted: false,
urgent: false,
has_thread: false,
ephemeral: false,
loading: false,
failed_to_mention_some_roles_in_thread: true,
suppress_notifications: false,
is_voice_message: false,
has_snapshot: false,
is_components_v2: false
}
```
Comment thread
lara-rium marked this conversation as resolved.
"""
@spec from_integer(raw_flags()) :: t
def from_integer(flag_value) do
boolean_list =
Enum.map(@flag_values, fn {flag, value} ->
{flag, (flag_value &&& value) == value}
end)

struct(__MODULE__, boolean_list)
end

@doc """
Convert a flag struct to an integer value.

## Examples

```elixir
iex> my_flags = %Nostrum.Struct.Message.Flags{
...> crossposted: false,
...> is_crosspost: true,
...> suppress_embeds: false,
...> source_message_deleted: false,
...> urgent: false,
...> has_thread: false,
...> ephemeral: false,
...> loading: false,
...> failed_to_mention_some_roles_in_thread: true,
...> suppress_notifications: false,
...> is_voice_message: false,
...> has_snapshot: false,
...> is_components_v2: false
...> }
iex> Nostrum.Struct.Message.Flags.to_integer(my_flags)
258
```
"""
@spec to_integer(t) :: raw_flags()
def to_integer(flag_struct) do
booleans =
flag_struct
|> Map.from_struct()
|> Map.to_list()

Enum.reduce(booleans, 0, fn {flag, enabled}, flag_value ->
case enabled do
true -> flag_value ||| @flag_values[flag]
false -> flag_value
end
end)
end
end
Loading