From bdf193ef89863062889647a11e19ba87923e4fd8 Mon Sep 17 00:00:00 2001 From: Brandt Hill Date: Sat, 11 May 2024 01:37:04 -0500 Subject: [PATCH] Refactor executable checks and add version check for non-forked youtube-dl --- config/config.exs | 4 +--- lib/nostrum/application.ex | 41 ++++++++++++++++++----------------- lib/nostrum/dummy.ex | 2 +- lib/nostrum/voice.ex | 44 +++++++++++++++++++++++++++++++++++++- lib/nostrum/voice/audio.ex | 10 ++++++--- 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/config/config.exs b/config/config.exs index da3677333..5e5ec874a 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,9 +1,7 @@ import Config config :nostrum, - token: "", - ffmpeg: "ffmpeg", - youtubedl: "youtube-dl" + token: "" config :logger, :console, metadata: [:shard, :guild, :channel] diff --git a/lib/nostrum/application.ex b/lib/nostrum/application.ex index d776280b0..875b39b03 100644 --- a/lib/nostrum/application.ex +++ b/lib/nostrum/application.ex @@ -4,6 +4,7 @@ defmodule Nostrum.Application do use Application alias Nostrum.Token + alias Nostrum.Voice require Logger @@ -41,31 +42,31 @@ 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) + ff = Voice.ffmpeg_executable() + yt = Voice.youtubedl_executable() + sl = Voice.streamlink_executable() - cond do - is_binary(ff) and is_nil(System.find_executable(ff)) -> + if ff do + if !System.find_executable(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 to suppress. + If you don't intend to use voice with ffmpeg, configure :nostrum, :ffmpeg to nil or false to suppress all voice warnings. """) + else + if yt && !System.find_executable(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 - 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 + if sl && !System.find_executable(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 + end end end diff --git a/lib/nostrum/dummy.ex b/lib/nostrum/dummy.ex index de6a469cd..9ba5d1154 100644 --- a/lib/nostrum/dummy.ex +++ b/lib/nostrum/dummy.ex @@ -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 diff --git a/lib/nostrum/voice.ex b/lib/nostrum/voice.ex index 679e13a45..a6de581d4 100644 --- a/lib/nostrum/voice.ex +++ b/lib/nostrum/voice.ex @@ -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 @@ -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. @@ -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 @@ -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(:has_checked_youtubedl_version, false) do + :persistent_term.put(:has_checked_youtubedl_version, true) + {:ok, _pid} = Task.start(fn -> check_youtubedl_version() end) + end + end + end + + defp maybe_warn(_type), do: :noop end diff --git a/lib/nostrum/voice/audio.ex b/lib/nostrum/voice/audio.ex index ab43b147a..8171ec5f5 100644 --- a/lib/nostrum/voice/audio.ex +++ b/lib/nostrum/voice/audio.ex @@ -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) @@ -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", "-"], @@ -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"], @@ -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"],