1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
|