mirror of
https://codeberg.org/godmaire/sergei.git
synced 2024-09-20 00:08:25 +00:00
refactor: move commands && add queue subcommands
This commit is contained in:
parent
da0f899eac
commit
7d57478dda
4 changed files with 158 additions and 133 deletions
129
lib/sergei/commands.ex
Normal file
129
lib/sergei/commands.ex
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
defmodule Sergei.Commands do
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
# Translate params to list of maps
|
||||||
|
opt = fn type, name, desc, opts ->
|
||||||
|
%{type: type, name: name, description: desc}
|
||||||
|
|> Map.merge(Enum.into(opts, %{}))
|
||||||
|
end
|
||||||
|
|
||||||
|
@play_opts [
|
||||||
|
opt.(3, "url", "URL of the audio to play", [])
|
||||||
|
]
|
||||||
|
|
||||||
|
@queue_add_opts [
|
||||||
|
opt.(3, "url", "URL of the audio to queue", required: true)
|
||||||
|
]
|
||||||
|
|
||||||
|
@queue_opts [
|
||||||
|
opt.(1, "add", "Add a song to the queue", options: @queue_add_opts)
|
||||||
|
]
|
||||||
|
|
||||||
|
@slash_commands [
|
||||||
|
{"ping", "Pong", []},
|
||||||
|
{"play", "Play a song or resume playback", @play_opts},
|
||||||
|
{"queue", "Manage the song queue", @queue_opts},
|
||||||
|
{"pause", "Pause media playback", []},
|
||||||
|
{"stop", "Stop media playback and leave the voice channel", []},
|
||||||
|
{"song", "What song is currently playing?", []}
|
||||||
|
]
|
||||||
|
|
||||||
|
def commands() do
|
||||||
|
Enum.map(@slash_commands, fn {name, description, options} ->
|
||||||
|
%{
|
||||||
|
name: name,
|
||||||
|
description: description,
|
||||||
|
options: options
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
# /ping
|
||||||
|
def do_command(%{data: %{name: "ping"}}) do
|
||||||
|
{:ok, "Pong"}
|
||||||
|
end
|
||||||
|
|
||||||
|
# /play <url>
|
||||||
|
def do_command(%{
|
||||||
|
guild_id: guild_id,
|
||||||
|
user: %{id: invoker_id},
|
||||||
|
data: %{name: "play", options: [%{name: "url", value: url}]}
|
||||||
|
}) do
|
||||||
|
case Sergei.VoiceStateCache.get_state(invoker_id) do
|
||||||
|
%{guild_id: id} = _res when guild_id != id ->
|
||||||
|
{:error, "You're not connected to a voice channel in this server."}
|
||||||
|
|
||||||
|
%{channel_id: channel_id} = _res ->
|
||||||
|
Sergei.Player.play(guild_id, channel_id, url)
|
||||||
|
|
||||||
|
nil ->
|
||||||
|
{:error, "You are not in a voice channel."}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# /play
|
||||||
|
def do_command(%{guild_id: guild_id, data: %{name: "play"}}) do
|
||||||
|
case Sergei.Player.resume(guild_id) do
|
||||||
|
:ok ->
|
||||||
|
{:ok, "Resuming playback..."}
|
||||||
|
|
||||||
|
:not_playing ->
|
||||||
|
{:ok, "I'm not playing anything right now."}
|
||||||
|
|
||||||
|
{:error, err} ->
|
||||||
|
Logger.error("Failed to resume media: #{err}")
|
||||||
|
{:error, "This is embarrasing..."}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# /queue <subcommand>
|
||||||
|
def do_command(%{
|
||||||
|
guild_id: guild_id,
|
||||||
|
data: %{name: "queue", options: opts}
|
||||||
|
}) do
|
||||||
|
subcommand = List.first(opts)
|
||||||
|
|
||||||
|
Sergei.Commands.Queue.handle(guild_id, subcommand.name, subcommand.options)
|
||||||
|
end
|
||||||
|
|
||||||
|
# /pause
|
||||||
|
def do_command(%{guild_id: guild_id, data: %{name: "pause"}}) do
|
||||||
|
case Sergei.Player.pause(guild_id) do
|
||||||
|
:ok ->
|
||||||
|
{:ok, "Pausing..."}
|
||||||
|
|
||||||
|
:not_playing ->
|
||||||
|
{:ok, "I'm not playing anything right now."}
|
||||||
|
|
||||||
|
{:error, err} ->
|
||||||
|
Logger.error("Failed to pause media: #{err}")
|
||||||
|
{:error, "This is embarrasing..."}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# /stop
|
||||||
|
def do_command(%{guild_id: guild_id, data: %{name: "stop"}}) do
|
||||||
|
case Sergei.Player.stop(guild_id) do
|
||||||
|
:ok ->
|
||||||
|
{:ok, "Bye!"}
|
||||||
|
|
||||||
|
:not_playing ->
|
||||||
|
{:ok, "I'm not playing anything right now."}
|
||||||
|
|
||||||
|
{:error, err} ->
|
||||||
|
Logger.error("Failed to stop media: #{err}")
|
||||||
|
{:error, "This is embarrasing..."}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# /song
|
||||||
|
def do_command(%{guild_id: guild_id, data: %{name: "song"}}) do
|
||||||
|
case Sergei.Player.get_current_song(guild_id) do
|
||||||
|
:not_playing ->
|
||||||
|
{:ok, "I'm not playing anything right now."}
|
||||||
|
|
||||||
|
url ->
|
||||||
|
{:ok, url}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
23
lib/sergei/commands/queue.ex
Normal file
23
lib/sergei/commands/queue.ex
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
defmodule Sergei.Commands.Queue do
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@spec handle(integer(), String.t(), [%{name: String.t(), value: String.t()}]) ::
|
||||||
|
{:ok, String.t()} | {:err, String.t()}
|
||||||
|
def handle(guild_id, "add", opts) do
|
||||||
|
[
|
||||||
|
%{name: "url", value: url}
|
||||||
|
] = opts
|
||||||
|
|
||||||
|
case Sergei.Player.queue_add(guild_id, url) do
|
||||||
|
:ok ->
|
||||||
|
{:ok, "Song queued."}
|
||||||
|
|
||||||
|
:not_playing ->
|
||||||
|
{:ok, "I'm not playing anything right now."}
|
||||||
|
|
||||||
|
{:error, err} ->
|
||||||
|
Logger.error("Failed to queue media: #{err}")
|
||||||
|
{:error, "This is embarassing..."}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,42 +4,12 @@ defmodule Sergei.Consumer do
|
||||||
require Logger
|
require Logger
|
||||||
alias Nostrum.Api
|
alias Nostrum.Api
|
||||||
|
|
||||||
# Translate params to list of maps
|
|
||||||
opt = fn type, name, desc, opts ->
|
|
||||||
%{type: type, name: name, description: desc}
|
|
||||||
|> Map.merge(Enum.into(opts, %{}))
|
|
||||||
end
|
|
||||||
|
|
||||||
@play_opts [
|
|
||||||
opt.(3, "url", "URL of the audio to play", [])
|
|
||||||
]
|
|
||||||
|
|
||||||
@queue_opts [
|
|
||||||
opt.(3, "url", "URL of the audio to queue", required: true)
|
|
||||||
]
|
|
||||||
|
|
||||||
@slash_commands [
|
|
||||||
{"ping", "Pong", []},
|
|
||||||
{"play", "Play a song or resume playback", @play_opts},
|
|
||||||
{"queue", "Queue a song to play next", @queue_opts},
|
|
||||||
{"pause", "Pause media playback", []},
|
|
||||||
{"stop", "Stop media playback and leave the voice channel", []},
|
|
||||||
{"song", "What song is currently playing?", []}
|
|
||||||
]
|
|
||||||
|
|
||||||
# Initialization of the Discord Client
|
# Initialization of the Discord Client
|
||||||
def handle_event({:READY, %{guilds: guilds} = _event, _ws_state}) do
|
def handle_event({:READY, %{guilds: guilds} = _event, _ws_state}) do
|
||||||
# Playing some tunes
|
# Playing some tunes
|
||||||
Api.update_status(:online, "some tunes", 0)
|
Api.update_status(:online, "some tunes", 0)
|
||||||
|
|
||||||
commands =
|
commands = Sergei.Commands.commands()
|
||||||
Enum.map(@slash_commands, fn {name, description, options} ->
|
|
||||||
%{
|
|
||||||
name: name,
|
|
||||||
description: description,
|
|
||||||
options: options
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
|
|
||||||
case Application.get_env(:sergei, :env) do
|
case Application.get_env(:sergei, :env) do
|
||||||
:prod ->
|
:prod ->
|
||||||
|
@ -72,7 +42,7 @@ defmodule Sergei.Consumer do
|
||||||
# Handle interactions
|
# Handle interactions
|
||||||
def handle_event({:INTERACTION_CREATE, interaction, _ws_state}) do
|
def handle_event({:INTERACTION_CREATE, interaction, _ws_state}) do
|
||||||
response =
|
response =
|
||||||
case do_command(interaction) do
|
case Sergei.Commands.do_command(interaction) do
|
||||||
{:ok, msg} ->
|
{:ok, msg} ->
|
||||||
%{type: 4, data: %{content: msg, flags: 2 ** 6}}
|
%{type: 4, data: %{content: msg, flags: 2 ** 6}}
|
||||||
|
|
||||||
|
@ -93,101 +63,4 @@ defmodule Sergei.Consumer do
|
||||||
def handle_event(_event) do
|
def handle_event(_event) do
|
||||||
:noop
|
:noop
|
||||||
end
|
end
|
||||||
|
|
||||||
# /ping
|
|
||||||
def do_command(%{data: %{name: "ping"}}) do
|
|
||||||
{:ok, "Pong"}
|
|
||||||
end
|
|
||||||
|
|
||||||
# /play <url>
|
|
||||||
def do_command(%{
|
|
||||||
guild_id: guild_id,
|
|
||||||
user: %{id: invoker_id},
|
|
||||||
data: %{name: "play", options: [%{name: "url", value: url}]}
|
|
||||||
}) do
|
|
||||||
case Sergei.VoiceStateCache.get_state(invoker_id) do
|
|
||||||
%{guild_id: id} = _res when guild_id != id ->
|
|
||||||
{:error, "You're not connected to a voice channel in this server."}
|
|
||||||
|
|
||||||
%{channel_id: channel_id} = _res ->
|
|
||||||
Sergei.Player.play(guild_id, channel_id, url)
|
|
||||||
|
|
||||||
nil ->
|
|
||||||
{:error, "You are not in a voice channel."}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# /play
|
|
||||||
def do_command(%{guild_id: guild_id, data: %{name: "play"}}) do
|
|
||||||
case Sergei.Player.resume(guild_id) do
|
|
||||||
:ok ->
|
|
||||||
{:ok, "Resuming playback..."}
|
|
||||||
|
|
||||||
:not_playing ->
|
|
||||||
{:ok, "I'm not playing anything right now."}
|
|
||||||
|
|
||||||
{:error, err} ->
|
|
||||||
Logger.error("Failed to resume media: #{err}")
|
|
||||||
{:error, "This is embarrasing..."}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# /queue <url>
|
|
||||||
def do_command(%{
|
|
||||||
guild_id: guild_id,
|
|
||||||
data: %{name: "queue", options: [%{name: "url", value: url}]}
|
|
||||||
}) do
|
|
||||||
case Sergei.Player.queue(guild_id, url) do
|
|
||||||
:ok ->
|
|
||||||
{:ok, "Song queued."}
|
|
||||||
|
|
||||||
:not_playing ->
|
|
||||||
{:ok, "I'm not playing anything right now."}
|
|
||||||
|
|
||||||
{:error, err} ->
|
|
||||||
Logger.error("Failed to queue media: #{err}")
|
|
||||||
{:error, "This is embarassing..."}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# /pause
|
|
||||||
def do_command(%{guild_id: guild_id, data: %{name: "pause"}}) do
|
|
||||||
case Sergei.Player.pause(guild_id) do
|
|
||||||
:ok ->
|
|
||||||
{:ok, "Pausing..."}
|
|
||||||
|
|
||||||
:not_playing ->
|
|
||||||
{:ok, "I'm not playing anything right now."}
|
|
||||||
|
|
||||||
{:error, err} ->
|
|
||||||
Logger.error("Failed to pause media: #{err}")
|
|
||||||
{:error, "This is embarrasing..."}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# /stop
|
|
||||||
def do_command(%{guild_id: guild_id, data: %{name: "stop"}}) do
|
|
||||||
case Sergei.Player.stop(guild_id) do
|
|
||||||
:ok ->
|
|
||||||
{:ok, "Bye!"}
|
|
||||||
|
|
||||||
:not_playing ->
|
|
||||||
{:ok, "I'm not playing anything right now."}
|
|
||||||
|
|
||||||
{:error, err} ->
|
|
||||||
Logger.error("Failed to stop media: #{err}")
|
|
||||||
{:error, "This is embarrasing..."}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# /song
|
|
||||||
def do_command(%{guild_id: guild_id, data: %{name: "song"}}) do
|
|
||||||
case Sergei.Player.get_current_song(guild_id) do
|
|
||||||
:not_playing ->
|
|
||||||
{:ok, "I'm not playing anything right now."}
|
|
||||||
|
|
||||||
url ->
|
|
||||||
{:ok, url}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,9 +24,9 @@ defmodule Sergei.Player do
|
||||||
GenServer.call(__MODULE__, {:play, guild_id, channel_id, url})
|
GenServer.call(__MODULE__, {:play, guild_id, channel_id, url})
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec queue(integer(), String.t()) :: :ok | :not_playing | {:error, String.t()}
|
@spec queue_add(integer(), String.t()) :: :ok | :not_playing | {:error, String.t()}
|
||||||
def queue(guild_id, url) do
|
def queue_add(guild_id, url) do
|
||||||
GenServer.call(__MODULE__, {:queue, guild_id, url})
|
GenServer.call(__MODULE__, {:queue_add, guild_id, url})
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec pause(integer()) :: :ok | :not_playing | {:error, String.t()}
|
@spec pause(integer()) :: :ok | :not_playing | {:error, String.t()}
|
||||||
|
@ -128,7 +128,7 @@ defmodule Sergei.Player do
|
||||||
|
|
||||||
# Queue
|
# Queue
|
||||||
@impl true
|
@impl true
|
||||||
def handle_call({:queue, guild_id, url}, _from, state) do
|
def handle_call({:queue_add, guild_id, url}, _from, state) do
|
||||||
%{queue: queue} = Map.fetch!(state, guild_id)
|
%{queue: queue} = Map.fetch!(state, guild_id)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue