Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nostrum.Api Module Decomposition #641

Merged
merged 45 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9d439b9
Update Message type typedoc from latest API docs
kyleboe Oct 20, 2024
9c97daf
Update buttons guide image from API docs
kyleboe Oct 20, 2024
d32e178
Update `Struct.Channel` with default_sort_order and default_forum_layout
kyleboe Oct 20, 2024
4150681
Remove id callout to match rest of typedocs
kyleboe Oct 20, 2024
d4969e2
Rename base to adapter to indicate direction towards building behavio…
kyleboe Oct 23, 2024
6d0350b
Add `Nostrum.Api.ApplicationCommand` module and functions
kyleboe Oct 23, 2024
77f0c27
Add `Nostrum.Api.AutoModeration` module and functions
kyleboe Oct 23, 2024
64ccea5
Add `Nostrum.Api.Channel` module and functions
kyleboe Oct 23, 2024
955c361
Adjust Api Ratelimited for base rename
kyleboe Oct 23, 2024
34874aa
Remove unused alias
kyleboe Oct 23, 2024
e32f4df
WIP begin delegating `Nostrum.Api` function calls to submodules
kyleboe Oct 23, 2024
aeff17e
Extract functions for Guild, Invite, MEssage, Poll, Role, ScheduledEv…
kyleboe Oct 25, 2024
a40b47f
Extract functions for Nostrum.Api.Thread
kyleboe Oct 25, 2024
b528049
Extract functions for Nostrum.Api.User
kyleboe Oct 25, 2024
dc5fd11
Extract functions for Nostrum.Api.Webhook
kyleboe Oct 25, 2024
508e00a
Extract functions for Interaction and Sticker
kyleboe Oct 25, 2024
3511716
Minimize diff and remove unused alias
kyleboe Oct 25, 2024
69d3c4b
Minimize diff
kyleboe Oct 25, 2024
10b1c99
Start moving api helper functions to Api.Helpers module
kyleboe Oct 25, 2024
938f55a
Update helpers.ex
kyleboe Oct 25, 2024
f211056
Add bypass for testing
kyleboe Oct 25, 2024
e4b462f
WIP Nostrum.Api delegate refactoring
kyleboe Oct 26, 2024
d1154c6
`Nostrum.Api` delegate refactoring and deprecation warnings
kyleboe Oct 26, 2024
1c135be
move type definitions to Nostrum.Api.Webhook
kyleboe Oct 26, 2024
2844303
alias missing modules in Nostrum.Api.Webhook
kyleboe Oct 26, 2024
323a3bc
Change doc "since" version to 1.x.x
kyleboe Oct 30, 2024
b2d9789
Add ATTACHMENT application command option type definition
kyleboe Oct 30, 2024
6a79403
Add PRIMARY_ENTRY_POINT constant for application commands
kyleboe Oct 30, 2024
d26e246
Merge branch 'Kraigie:master' into master
kyleboe Nov 1, 2024
47c7591
Merge pull request #1 from kyleboe/api-module-decomp
kyleboe Nov 1, 2024
677e697
Use alphabetical ordering of aliases
kyleboe Nov 1, 2024
81a4870
Add module documentation for Discord API modules
kyleboe Nov 1, 2024
7081a6d
Update docs and allowed trigger types for AutoModerationRule
kyleboe Nov 1, 2024
798b8a6
Update docs and allowed action types for AutoModerationRule.Action
kyleboe Nov 1, 2024
888b8e1
Update docs naming to match discord api docs
kyleboe Nov 1, 2024
5e1ba95
Remove bypass and rebuild lockfile
kyleboe Nov 1, 2024
8cbd7d1
Update voice API calls to use proper module functions
kyleboe Nov 1, 2024
af87241
alias Self and use in Voice module
kyleboe Nov 1, 2024
2d75ce4
Update references to new API modules in docs and internal functions
kyleboe Nov 1, 2024
fceb566
Update references to new API modules in docs
kyleboe Nov 1, 2024
3315284
Move helper functions out of Nostrum.Api module
kyleboe Nov 5, 2024
4eb1a42
Properly reference `maybe_convert_date_time`
kyleboe Nov 5, 2024
58440b8
Use proper alias for ConsumerGroup example
kyleboe Nov 5, 2024
ef45f06
Merge branch 'Kraigie:master' into master
kyleboe Nov 5, 2024
d4058b8
Move Role API endpoints to Guild module
kyleboe Nov 12, 2024
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ for a full example.
defmodule ExampleConsumer do
use Nostrum.Consumer

alias Nostrum.Api
alias Nostrum.Api.Message

def handle_event({:MESSAGE_CREATE, msg, _ws_state}) do
case msg.content do
"ping!" ->
Api.create_message(msg.channel_id, "I copy and pasted this code")
Message.create(msg.channel_id, "I copy and pasted this code")
_ ->
:ignore
end
Expand Down
7 changes: 4 additions & 3 deletions examples/audio_player_example.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ end
defmodule AudioPlayerConsumer do
use Nostrum.Consumer

alias Nostrum.Api
alias Nostrum.Api.ApplicationCommand
alias Nostrum.Api.Interaction
alias Nostrum.Cache.GuildCache
alias Nostrum.Voice

Expand Down Expand Up @@ -66,7 +67,7 @@ defmodule AudioPlayerConsumer do
# with your guild_id as the argument
def create_guild_commands(guild_id) do
Enum.each(@commands, fn {name, description, options} ->
Api.create_guild_application_command(guild_id, %{
ApplicationCommand.create_guild_command(guild_id, %{
name: name,
description: description,
options: options
Expand All @@ -88,7 +89,7 @@ defmodule AudioPlayerConsumer do
_ -> ":white_check_mark:"
end

Api.create_interaction_response(interaction, %{type: 4, data: %{content: message}})
Interaction.create_response(interaction, %{type: 4, data: %{content: message}})
end

def handle_event({:VOICE_SPEAKING_UPDATE, payload, _ws_state}) do
Expand Down
8 changes: 4 additions & 4 deletions examples/cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ end
defmodule ExampleCommands do
import Nostrum.Snowflake, only: [is_snowflake: 1]

alias Nostrum.Api
alias Nostrum.Api.Message
alias Nostrum.Cache.{GuildCache, UserCache}
alias Nostrum.Struct.User

Expand Down Expand Up @@ -68,7 +68,7 @@ defmodule ExampleCommands do
get_cached_with_fallback(user_id, &UserCache.get/1, &Api.get_user/1),
{:ok, %{name: guild_name}} <-
get_cached_with_fallback(guild_id, &GuildCache.get/1, &Api.get_guild/1) do
Api.create_message(
Message.create(
channel_id,
"""
ID #{message_user_id} belongs to: #{User.full_name(user)}
Expand All @@ -79,12 +79,12 @@ defmodule ExampleCommands do
# Since we have multiple failure patterns from the combination of `Integer.parse/2`
# and `is_snowflake/1`, we'll use the identifier as the term to match on instead.
{_invalid_id, :parse_id} ->
Api.create_message(channel_id, "Make sure you entered a valid User ID")
Message.create(channel_id, "Make sure you entered a valid User ID")

# The cache + API failure case. For now, lets just return the stringified failure
# reason of whatever the API returned. Up to you if you want to make it all nice and pretty.
{:error, reason} ->
Api.create_message(channel_id, "Failed to retrieve all required info: #{inspect(reason)}")
Message.create(channel_id, "Failed to retrieve all required info: #{inspect(reason)}")
end
end

Expand Down
6 changes: 3 additions & 3 deletions examples/event_consumer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ end
defmodule ExampleConsumer do
use Nostrum.Consumer

alias Nostrum.Api
alias Nostrum.Api.Message

def handle_event({:MESSAGE_CREATE, msg, _ws_state}) do
case msg.content do
"!sleep" ->
Api.create_message(msg.channel_id, "Going to sleep...")
Message.create(msg.channel_id, "Going to sleep...")
# This won't stop other events from being handled.
Process.sleep(3000)

"!ping" ->
Api.create_message(msg.channel_id, "pyongyang!")
Message.create(msg.channel_id, "pyongyang!")

"!raise" ->
# This won't crash the entire Consumer.
Expand Down
20 changes: 10 additions & 10 deletions guides/cheat-sheets/api.cheatmd
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ UTC time is: #{DateTime.to_iso8601(utc_now)}
Atom table size is: #{atom_count}
"""

Nostrum.Api.create_message(msg.channel_id, content)
Nostrum.Api.Message.create(msg.channel_id, content)
```

### Sending a message with an embed
Expand All @@ -35,15 +35,15 @@ embed =
# set inline attribute to true
|> put_field("Field 2", "More test", true)

Nostrum.Api.create_message(msg.channel_id, embeds: [embed])
Nostrum.Api.Message.create(msg.channel_id, embeds: [embed])
```

You can look at the documentation in `m:Nostrum.Struct.Embed#module-using-structs` for more advanced usage.

### Upload an attachment

```elixir
Nostrum.Api.create_message(
Nostrum.Api.Message.create(
msg.channel_id,
files: [
# file from filesystem
Expand All @@ -59,7 +59,7 @@ Nostrum.Api.create_message(
With a mention:

```elixir
Nostrum.Api.create_message(
Nostrum.Api.Message.create(
msg.channel_id,
content: "Hello!",
message_reference: %{message_id: msg.id}
Expand All @@ -69,7 +69,7 @@ Nostrum.Api.create_message(
Without a mention:

```elixir
Nostrum.Api.create_message(
Nostrum.Api.Message.create(
msg.channel_id,
content: "Hello!",
message_reference: %{message_id: msg.id},
Expand All @@ -88,14 +88,14 @@ poll = Poll.create_poll(
|> Poll.put_answer("Yes!", default_emoji: "\u2705")
|> Poll.put_answer("No!", default_emoji: "\u274C")

Api.create_message(channel_id, poll: poll)
Nostrum.Api.Message.create(channel_id, poll: poll)
```

### React to a message

Using a default emoji (unicode representation):
```elixir
Nostrum.Api.create_reaction(
Nostrum.Api.Message.react(
msg.channel_id,
msg.id,
"👾"
Expand All @@ -109,7 +109,7 @@ emoji = %Nostrum.Struct.Emoji{
id: 1228698654022434866
}

Nostrum.Api.create_reaction(msg.channel_id, msg.id, emoji)
Nostrum.Api.Message.react(msg.channel_id, msg.id, emoji)
```

## Miscellaneous
Expand All @@ -118,7 +118,7 @@ Nostrum.Api.create_reaction(msg.channel_id, msg.id, emoji)
### Update the bot status

```elixir
Nostrum.Api.update_status(
Nostrum.Api.Self.update_status(
:dnd,
"craigs cats",
3 # Watching status
Expand All @@ -131,7 +131,7 @@ You can also update a single shard with `Nostrum.Api.update_shard_status/5`.
```elixir
image = "data:image/png;base64,..."

Nostrum.Api.create_guild_emoji(
Nostrum.Api.Guild.create_emoji(
msg.guild_id,
name: "nostrum",
image: image
Expand Down
33 changes: 3 additions & 30 deletions guides/intro/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,13 @@ Discord's API. Method names are copied closely from the documentation to
eliminate any confusion about what a method does, as well as to allow users to
easily lookup the endpoints in the official API documentation.

For a full listing of method definitions, please see the `Nostrum.Api` module.


## Banged (`!`) API methods

A lot of methods have a `banged` version of themselves. This is a common Elixir
idiom hailing from Elixir's style of failing fast.

By default, the API method will return a tuple like one of the following:

```elixir
# Success
{:ok, msg} = Nostrum.Api.create_message(179679229036724225, "456")

# Failure
{:error, reason} = Nostrum.Api.create_message(123, "eat my shorts api")
```

A banged method, instead of returning an `error` tuple, will throw an error. If
successful, it will directly return the response with no `:ok` tuple.

```elixir
# Success
msg = Nostrum.Api.create_message!(179679229036724225, "456")

# Failure - Throws an error
Nostrum.Api.create_message!(123, "eat my shorts api")
```
For a listing of method definitions, please see the submodules of `Nostrum.Api`.


## Abstractions

When appropriate, some helpers are defined to make interacting with the API
simpler. An example of this is `Nostrum.Api.get_channel_messages/3`. By default
simpler. An example of this is `Nostrum.Api.Channel.messages/3`. By default
this endpoint only allows the retrieval of `100` messages at a time. A general
use case will have a user wanting more messages than that, thus nostrum handles
the retrieval of any number of messages for the user.
Expand All @@ -62,7 +35,7 @@ asynchronously or not, nostrum funnels all requests through the

If you only want to use the REST portion of the provided API, the only process
needed is the ratelimiter, which can be manually started by calling
`Nostrum.Api.Ratelimiter.start_link/1`.
`Nostrum.Api.Ratelimiter.start_link/1`.

If you don't want to start nostrum, you can add `runtime: false` to the
dependency options. If you're using `mix release`, all `runtime: false` deps
Expand Down
15 changes: 8 additions & 7 deletions guides/intro/application_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ command = %{
```

To register this command on the guild, we simply pass it to
`Nostrum.Api.create_guild_application_command/2`:
`Nostrum.Api.ApplicationCommand.create_guild_command/2`:

```elixir
Nostrum.Api.create_guild_application_command(guild_id, command)
Nostrum.Api.ApplicationCommand.create_guild_command(guild_id, command)
```

You can register the command in the ``:READY`` gateway event handler.
Expand Down Expand Up @@ -97,14 +97,15 @@ separate operation modes:

```elixir
alias Nostrum.Api
alias Nostrum.Api.Role
alias Nostrum.Struct.Interaction

defp manage_role(%Interaction{data: %{options: [%{value: role_id}, %{value: "assign"}]}} = interaction) do
Api.add_guild_member_role(interaction.guild_id, interaction.member.user_id, role_id)
Role.add_member(interaction.guild_id, interaction.member.user_id, role_id)
end

defp manage_role(%Interaction{data: %{options: [%{value: role_id}, %{value: "remove"}]}} = interaction) do
Api.remove_guild_member_role(interaction.guild_id, interaction.member.user_id, role_id)
Role.remove_member(interaction.guild_id, interaction.member.user_id, role_id)
end

def handle_event({:INTERACTION_CREATE, %Interaction{data: %{name: "role"}} = interaction, _ws_state}) do
Expand All @@ -118,18 +119,18 @@ that you would use for regular commands.

## Responding to interactions

To respond to interactions, use ``Nostrum.Api.create_interaction_response/2``:
To respond to interactions, use ``Nostrum.Api.Interaction.create_response/2``:

```elixir
defp manage_role(%Interaction{data: %{options: [%{value: role_id}, %{value: "assign"}]}} = interaction) do
Api.add_guild_member_role(interaction.guild_id, interaction.member.user_id, role_id)
Role.add_member(interaction.guild_id, interaction.member.user_id, role_id)
response = %{
type: 4, # ChannelMessageWithSource
data: %{
content: "role assigned"
}
}
Api.create_interaction_response(interaction, response)
Api.Interaction.create_response(interaction, response)
end
```

Expand Down
Loading