Skip to content
New issue

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

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

Already on GitHub? # to your account

Refactor executable checks and add version check for non-forked youtube-dl #594

Merged
merged 2 commits into from
May 12, 2024
Merged
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
4 changes: 1 addition & 3 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import Config

config :nostrum,
token: "",
ffmpeg: "ffmpeg",
youtubedl: "youtube-dl"
token: ""

config :logger, :console, metadata: [:shard, :guild, :channel]

Expand Down
65 changes: 39 additions & 26 deletions lib/nostrum/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule Nostrum.Application do
use Application

alias Nostrum.Token
alias Nostrum.Voice

require Logger

Expand Down Expand Up @@ -41,34 +42,46 @@ defmodule Nostrum.Application do
end

defp check_executables do
ff = Application.get_env(:nostrum, :ffmpeg)
yt = Application.get_env(:nostrum, :youtubedl)
sl = Application.get_env(:nostrum, :streamlink)

cond do
is_binary(ff) and is_nil(System.find_executable(ff)) ->
Logger.warning("""
#{ff} was not found in your path. By default, Nostrum requires ffmpeg to use voice.
If you don't intend to use voice with ffmpeg, configure :nostrum, :ffmpeg to nil to suppress.
""")

is_binary(yt) and is_nil(System.find_executable(yt)) ->
Logger.warning("""
#{yt} was not found in your path. Nostrum supports youtube-dl for voice.
If you don't require youtube-dl support, configure :nostrum, :youtubedl to nil to suppress.
""")

is_binary(sl) and is_nil(System.find_executable(sl)) ->
Logger.warning("""
#{sl} was not found in your path. Nostrum supports streamlink for voice.
If you don't require streamlink support, configure :nostrum, :streamlink to nil to suppress.
""")

true ->
:ok
end
ff = Voice.ffmpeg_executable()
yt = Voice.youtubedl_executable()
sl = Voice.streamlink_executable()

ff_path = if ff, do: System.find_executable(ff)
yt_path = if yt, do: System.find_executable(yt)
sl_path = if sl, do: System.find_executable(sl)

check_ffmpeg(ff_path, ff)
check_ytdl(ff_path, yt, yt_path)
check_streamlink(ff_path, sl, sl_path)
end

defp check_ffmpeg(_ff_path = nil, ff) when is_binary(ff) do
Logger.warning("""
#{ff} was not found in your path. By default, Nostrum requires ffmpeg to use voice.
If you don't intend to use voice with ffmpeg, configure :nostrum, :ffmpeg to nil or false to suppress all voice warnings.
""")
end

defp check_ffmpeg(_ff_path, _ff), do: :noop

defp check_ytdl(ff_path, yt, _yt_path = nil) when is_binary(ff_path) and is_binary(yt) do
Logger.warning("""
#{yt} was not found in your path. Nostrum supports youtube-dl for voice.
If you don't require youtube-dl support, configure :nostrum, :youtubedl to nil or false to suppress.
""")
end

defp check_ytdl(_ff_path, _yt, _yt_path), do: :noop

defp check_streamlink(ff_path, sl, _sl_path = nil) when is_binary(ff_path) and is_binary(sl) do
Logger.warning("""
#{sl} was not found in your path. Nostrum supports streamlink for voice.
If you don't require streamlink support, configure :nostrum, :streamlink to nil or false to suppress.
""")
end

defp check_streamlink(_ff_path, _sl, _sl_path), do: :noop

defp check_otp_version do
_module_info = :pg.module_info()

Expand Down
2 changes: 1 addition & 1 deletion lib/nostrum/dummy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule DummySupervisor do
end

def init(_args) do
children = for id <- 0..1, do: Supervisor.child_spec({DummyConsumer, []}, id: id)
children = [DummyConsumer]
Supervisor.init(children, strategy: :one_for_one)
end
end
Expand Down
44 changes: 43 additions & 1 deletion lib/nostrum/voice.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ defmodule Nostrum.Voice do
"""

alias Nostrum.Api
alias Nostrum.Struct.{Channel, Guild, VoiceState, VoiceWSState}
alias Nostrum.Struct.Channel
alias Nostrum.Struct.Guild
alias Nostrum.Struct.VoiceState
alias Nostrum.Struct.VoiceWSState
alias Nostrum.Voice.Audio
alias Nostrum.Voice.Opus
alias Nostrum.Voice.Ports
Expand Down Expand Up @@ -121,6 +124,13 @@ defmodule Nostrum.Voice do
GenServer.cast(Nostrum.VoiceStateMap, {:remove, guild_id, pre_cleanup_args})
end

@doc false
defdelegate ffmpeg_executable, to: Audio
@doc false
defdelegate youtubedl_executable, to: Audio
@doc false
defdelegate streamlink_executable, to: Audio

@doc """
Joins or moves the bot to a voice channel.

Expand Down Expand Up @@ -242,6 +252,8 @@ defmodule Nostrum.Voice do
"""
@spec play(Guild.id(), play_input(), play_type(), keyword()) :: :ok | {:error, String.t()}
def play(guild_id, input, type \\ :url, options \\ []) do
maybe_warn(type)

voice = get_voice(guild_id)

cond do
Expand Down Expand Up @@ -834,4 +846,34 @@ defmodule Nostrum.Voice do
end

defp persistent_args(_voice), do: []

unless Application.compile_env(:nostrum, :suppress_youtubedl_version, false) do
@ytdl_old_version "2021.12.17"

defp check_youtubedl_version do
with ytdl when is_binary(ytdl) <- youtubedl_executable(),
["youtube-dl" | _] <- ytdl |> Path.basename() |> String.split("."),
{version, 0} <- System.cmd(ytdl, ["--version"]),
version when version <= @ytdl_old_version <- String.trim(version) do
Logger.warning("""
Configured youtube-dl installation '#{System.find_executable(ytdl)}' is version #{version}.

This version no longer compatible with recent YouTube updates.

It is recommended to configure :nostrum, :youtubedl to point to a maintained fork such as 'yt-dlp'.

If you know what you are doing, configure :nostrum, :suppress_youtubedl_version to `true` to suppress this.
""")
end
end

defp maybe_warn(:ytdl) do
unless :persistent_term.get(:nostrum_has_checked_youtubedl_version, false) do
:persistent_term.put(:nostrum_has_checked_youtubedl_version, true)
{:ok, _pid} = Task.start(fn -> check_youtubedl_version() end)
end
end
end

defp maybe_warn(_type), do: :noop
end
10 changes: 7 additions & 3 deletions lib/nostrum/voice/audio.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ defmodule Nostrum.Voice.Audio do

def encryption_mode, do: @encryption_mode

def ffmpeg_executable, do: Application.get_env(:nostrum, :ffmpeg, @ffmpeg)
def youtubedl_executable, do: Application.get_env(:nostrum, :youtubedl, @ytdl)
def streamlink_executable, do: Application.get_env(:nostrum, :streamlink, @streamlink)

# How many consecutive packets to send before resting
def frames_per_burst,
do: Application.get_env(:nostrum, :audio_frames_per_burst, @frames_per_burst)
Expand Down Expand Up @@ -166,7 +170,7 @@ defmodule Nostrum.Voice.Audio do
def spawn_youtubedl(url) do
res =
Ports.execute(
Application.get_env(:nostrum, :youtubedl, @ytdl),
youtubedl_executable(),
[
["-f", "bestaudio"],
["-o", "-"],
Expand All @@ -189,7 +193,7 @@ defmodule Nostrum.Voice.Audio do
def spawn_streamlink(url) do
res =
Ports.execute(
Application.get_env(:nostrum, :streamlink, @streamlink),
streamlink_executable(),
[
["--stdout"],
["--quiet"],
Expand Down Expand Up @@ -226,7 +230,7 @@ defmodule Nostrum.Voice.Audio do

res =
Ports.execute(
Application.get_env(:nostrum, :ffmpeg, @ffmpeg),
ffmpeg_executable(),
[
ffmpeg_options(options, input_url),
["-ac", "2"],
Expand Down