aboutsummaryrefslogtreecommitdiff
path: root/lib/audio/util.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/audio/util.ex')
-rw-r--r--lib/audio/util.ex114
1 files changed, 114 insertions, 0 deletions
diff --git a/lib/audio/util.ex b/lib/audio/util.ex
new file mode 100644
index 0000000..f45af4e
--- /dev/null
+++ b/lib/audio/util.ex
@@ -0,0 +1,114 @@
+defmodule Thulani.Audio.Util do
+ @spec stream_type(Nostrum.Voice.play_input()) ::
+ {:ok, Nostrum.Voice.play_type()} | {:error, atom()}
+
+ def stream_type(ref) when is_binary(ref) do
+ cond do
+ ytdl_link?(ref) -> {:ok, :ytdl}
+ streamlink?(ref) -> {:ok, :stream}
+ valid_url?(ref) -> {:ok, :url}
+ true -> {:ok, :pipe}
+ end
+ end
+
+ def stream_type(_ref) do
+ {:error, :invalid}
+ end
+
+ @spec ytdl_link?(String.t()) :: boolean
+ def ytdl_link?(s) when is_binary(s) do
+ valid_url?(s) and
+ ytdl_checks()
+ |> any_check?(s)
+ end
+
+ def ytdl_link?(_s), do: false
+
+ @spec streamlink?(String.t()) :: boolean
+ def streamlink?(s) when is_binary(s) do
+ valid_url?(s) and streamlink_checks() |> any_check?(s)
+ end
+
+ def streamlink?(_s), do: false
+
+ def valid_url?(s), do: String.match?(s, ~r/^https:\/\/.*/i)
+
+ def ytdl_checks, do: [&youtube_link?/1, &vimeo_link?/1]
+ def streamlink_checks, do: [&twitch_link?/1]
+
+ def youtube_link?(s),
+ do: String.match?(s, youtube_regex())
+
+ def vimeo_link?(s),
+ do: String.match?(s, vimeo_regex())
+
+ def twitch_link?(s),
+ do: String.match?(s, twitch_regex())
+
+ def youtube_regex, do: ~r/^https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be)\/.*/i
+ def vimeo_regex, do: ~r/^https?:\/\/(?:www\.)?(?:vimeo\.com)\/.*/i
+ def twitch_regex, do: ~r/^https?:\/\/(?:www\.)?(?:twitch\.com)\/.*/i
+
+ defp any_check?(checks, s) do
+ checks
+ |> Stream.map(fn check -> check.(s) end)
+ |> Enum.reduce(false, fn acc, x -> acc or x end)
+ end
+
+ def wait_ready(guild, interval \\ 100, count \\ 10) do
+ wait_for(guild, interval, count, &Nostrum.Voice.ready?/1)
+ end
+
+ def wait_playing(guild, interval \\ 200, count \\ 30) do
+ wait_for(guild, interval, count, &Nostrum.Voice.playing?/1)
+ end
+
+ def wait_no_channel(guild, interval \\ 200, count \\ 30) do
+ wait_for(guild, interval, count, fn guild -> no_channel?(guild) end)
+ end
+
+ def wait_disconnected(guild, interval \\ 200, count \\ 30) do
+ wait_for(guild, interval, count, fn guild -> disconnected?(guild) end)
+ end
+
+ defp wait_for(guild, interval, count, check) do
+ unless check.(guild) do
+ [playing] =
+ Stream.unfold(0, fn i ->
+ Process.sleep(interval)
+ playing_state = check.(guild)
+ {playing_state, i + 1}
+ end)
+ |> Thulani.Util.Stream.take_until(&Function.identity/1)
+ |> Stream.take(count)
+ |> Enum.take(-1)
+
+ playing
+ else
+ true
+ end
+ end
+
+ def connected?(guild) do
+ voice_state = Nostrum.Voice.get_voice(guild)
+ !is_nil(voice_state) && !is_nil(voice_state.channel_id)
+ end
+
+ def disconnect(guild) do
+ voice_state = Nostrum.Voice.get_voice(guild)
+ Nostrum.Voice.leave_channel(guild)
+
+ if not is_nil(voice_state) do
+ Nostrum.Voice.Session.close_connection(voice_state.session_pid)
+ end
+ end
+
+ def disconnected?(guild) do
+ Nostrum.Voice.get_voice(guild) |> is_nil
+ end
+
+ def no_channel?(guild) do
+ voice_state = Nostrum.Voice.get_voice(guild)
+ !is_nil(voice_state) && is_nil(voice_state.channel_id)
+ end
+end