Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F665923
icecast.ex
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
3 KB
Subscribers
None
icecast.ex
View Options
defmodule
Nola.Icecast
do
use
GenServer
require
Logger
@hackney_pool
:default
@httpoison_opts
[
hackney
:
[
pool
:
@hackney_pool
]]
@fuse
__MODULE__
def
start_link
,
do
:
GenServer
.
start_link
(
__MODULE__
,
[],
[])
def
init
(
_
)
do
GenServer
.
cast
(
self
(),
:poll
)
{
:ok
,
nil
}
end
def
handle_cast
(
:poll
,
state
)
do
state
=
poll
(
state
)
{
:noreply
,
state
}
end
def
handle_info
(
:poll
,
state
)
do
state
=
poll
(
state
)
{
:noreply
,
state
}
end
defp
poll
(
state
)
do
state
=
case
request
(
base_url
(),
:get
)
do
{
:ok
,
%
HTTPoison.Response
{
status_code
:
200
,
body
:
body
}}
->
# update_json_stats(Jason.decode(body))
stats
=
update_stats
(
body
)
if
state
!=
stats
do
Logger
.
info
(
"Icecast Update: "
<>
inspect
(
stats
))
Nola.IcecastAgent
.
update
(
stats
)
Registry
.
dispatch
(
Nola.BroadcastRegistry
,
"icecast"
,
fn
ws
->
for
{
pid
,
_
}
<-
ws
,
do
:
send
(
pid
,
{
:icecast
,
stats
})
end
)
stats
else
state
end
error
->
Logger
.
error
(
"Icecast HTTP Error:
#{
inspect
(
error
)
}
"
)
state
end
interval
=
Application
.
get_env
(
:nola
,
:icecast_poll_interval
,
60_000
)
:timer
.
send_after
(
interval
,
:poll
)
state
end
defp
update_stats
(
html
)
do
raw
=
Floki
.
find
(
html
,
"div.roundbox"
)
|>
Enum
.
map
(
fn
html
->
html
=
Floki
.
raw_html
(
html
)
[{
"h3"
,
_
,
[
"Mount Point /"
<>
mount
]}]
=
Floki
.
find
(
html
,
"h3.mount"
)
stats
=
Floki
.
find
(
html
,
"tr"
)
|>
Enum
.
map
(
fn
{
"tr"
,
_
,
tds
}
->
[{
"td"
,
_
,
keys
},
{
"td"
,
_
,
values
}]
=
tds
key
=
List
.
first
(
keys
)
value
=
List
.
first
(
values
)
{
key
,
value
}
end
)
|>
Enum
.
into
(
Map
.
new
())
{
mount
,
stats
}
end
)
|>
Enum
.
into
(
Map
.
new
())
live?
=
if
Map
.
get
(
raw
[
"live"
],
"Content Type:"
,
false
),
do
:
true
,
else
:
false
np
=
if
live?
do
raw
[
"live"
][
"Currently playing:"
]
else
raw
[
"autodj"
][
"Currently playing:"
]
end
genre
=
raw
[
"live"
][
"Genre:"
]
||
nil
%{
np
:
np
||
""
,
live
:
live?
||
false
,
genre
:
genre
}
end
defp
update_json_stats
({
:ok
,
body
})
do
Logger
.
debug
(
"JSON STATS:
#{
inspect
(
body
)
}
"
)
end
defp
update_json_stats
(
error
)
do
Logger
.
error
(
"Failed to decode JSON Stats:
#{
inspect
(
error
)
}
"
)
end
defp
request
(
uri
,
method
,
body
\\
[],
headers
\\
[])
do
headers
=
[{
"user-agent"
,
"Nola-API[115ans.net, sys.115ans.net] href@random.sh"
}]
++
headers
options
=
@httpoison_opts
# :fuse.ask(@fuse, :sync) do
case
:ok
do
:ok
->
run_request
(
method
,
uri
,
body
,
headers
,
options
)
:blown
->
:blown
end
end
# This is to work around hackney's behaviour of returning `{:error, :closed}` when a pool connection has been closed
# (keep-alive expired). We just retry the request immediatly up to five times.
defp
run_request
(
method
,
uri
,
body
,
headers
,
options
),
do
:
run_request
(
method
,
uri
,
body
,
headers
,
options
,
0
)
defp
run_request
(
method
,
uri
,
body
,
headers
,
options
,
retries
)
when
retries
<
4
do
case
HTTPoison
.
request
(
method
,
uri
,
body
,
headers
,
options
)
do
{
:error
,
:closed
}
->
run_request
(
method
,
uri
,
body
,
headers
,
options
,
retries
+
1
)
other
->
other
end
end
defp
run_request
(
method
,
uri
,
body
,
headers
,
options
,
_exceeded_retries
),
do
:
{
:error
,
:unavailable
}
#
# -- URIs
#
defp
stats_json_url
do
base_url
()
<>
"/status-json.xsl"
end
defp
base_url
do
"http://91.121.59.45:8089"
end
end
File Metadata
Details
Attached
Mime Type
text/x-ruby
Expires
Sat, Feb 28, 11:29 AM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
87326
Default Alt Text
icecast.ex (3 KB)
Attached To
rNOLA Nola
Event Timeline
Log In to Comment