Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F77415
last_fm.ex
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Subscribers
None
last_fm.ex
View Options
defmodule
Nola.Plugins.LastFm
do
require
Logger
@moduledoc
"""
#
last.fm
* **!lastfm|np `[nick|username]`**
* **.lastfm|np**
* **+lastfm, -lastfm `<username last.fm>; ?lastfm`** Configurer un nom d'utilisateur last.fm
"""
@single_trigger
~w(lastfm np)
@pubsub_topics
~w(trigger:lastfm trigger:np)
defstruct
dets
:
nil
def
irc_doc
,
do
:
@moduledoc
def
start_link
()
do
GenServer
.
start_link
(
__MODULE__
,
[],
name
:
__MODULE__
)
end
def
init
([])
do
regopts
=
[
type
:
__MODULE__
]
for
t
<-
@pubsub_topics
,
do
:
{
:ok
,
_
}
=
Registry
.
register
(
Nola.PubSub
,
t
,
type
:
__MODULE__
)
dets_filename
=
(
Nola
.
data_path
()
<>
"/"
<>
"lastfm.dets"
)
|>
String
.
to_charlist
{
:ok
,
dets
}
=
:dets
.
open_file
(
dets_filename
,
[])
{
:ok
,
%
__MODULE__
{
dets
:
dets
}}
end
def
handle_info
({
:irc
,
:trigger
,
"lastfm"
,
message
=
%{
trigger
:
%{
type
:
:plus
,
args
:
[
username
]}}},
state
)
do
username
=
String
.
strip
(
username
)
:ok
=
:dets
.
insert
(
state
.
dets
,
{
message
.
account
.
id
,
username
})
message
.
replyfun
.
(
"
#{
message
.
sender
.
nick
}
: nom d'utilisateur last.fm configuré: \"
#{
username
}
\"."
)
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
"lastfm"
,
message
=
%{
trigger
:
%{
type
:
:minus
,
args
:
[]}}},
state
)
do
text
=
case
:dets
.
lookup
(
state
.
dets
,
message
.
account
.
id
)
do
[{
_nick
,
_username
}]
->
:dets
.
delete
(
state
.
dets
,
message
.
account
.
id
)
message
.
replyfun
.
(
"
#{
message
.
sender
.
nick
}
: nom d'utilisateur last.fm enlevé."
)
_
->
nil
end
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
"lastfm"
,
message
=
%{
trigger
:
%{
type
:
:query
,
args
:
[]}}},
state
)
do
text
=
case
:dets
.
lookup
(
state
.
dets
,
message
.
account
.
id
)
do
[{
_nick
,
username
}]
->
message
.
replyfun
.
(
"
#{
message
.
sender
.
nick
}
:
#{
username
}
."
)
_
->
nil
end
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
_
,
message
=
%{
trigger
:
%{
type
:
:bang
,
args
:
[]}}},
state
)
do
irc_now_playing
(
message
.
account
.
id
,
message
,
state
)
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
_
,
message
=
%{
trigger
:
%{
type
:
:bang
,
args
:
[
nick_or_user
]}}},
state
)
do
irc_now_playing
(
nick_or_user
,
message
,
state
)
{
:noreply
,
state
}
end
def
handle_info
({
:irc
,
:trigger
,
_
,
message
=
%{
trigger
:
%{
type
:
:dot
}}},
state
)
do
members
=
Nola.Membership
.
members
(
message
.
network
,
message
.
channel
)
foldfun
=
fn
({
nick
,
user
},
acc
)
->
[{
nick
,
user
}
|
acc
]
end
usernames
=
:dets
.
foldl
(
foldfun
,
[],
state
.
dets
)
|>
Enum
.
uniq
()
|>
Enum
.
filter
(
fn
({
acct
,
_
})
->
Enum
.
member?
(
members
,
acct
)
end
)
|>
Enum
.
map
(
fn
({
_
,
u
})
->
u
end
)
for
u
<-
usernames
,
do
:
irc_now_playing
(
u
,
message
,
state
)
{
:noreply
,
state
}
end
def
handle_info
(
info
,
state
)
do
{
:noreply
,
state
}
end
def
terminate
(
_reason
,
state
)
do
if
state
.
dets
do
:dets
.
sync
(
state
.
dets
)
:dets
.
close
(
state
.
dets
)
end
:ok
end
defp
irc_now_playing
(
nick_or_user
,
message
,
state
)
do
nick_or_user
=
String
.
strip
(
nick_or_user
)
id_or_user
=
if
account
=
Nola.Account
.
get
(
nick_or_user
)
||
Nola.Account
.
find_always_by_nick
(
message
.
network
,
message
.
channel
,
nick_or_user
)
do
account
.
id
else
nick_or_user
end
username
=
case
:dets
.
lookup
(
state
.
dets
,
id_or_user
)
do
[{
_
,
username
}]
->
username
_
->
id_or_user
end
case
now_playing
(
username
)
do
{
:error
,
text
}
when
is_binary
(
text
)
->
message
.
replyfun
.
(
text
)
{
:ok
,
map
}
when
is_map
(
map
)
->
track
=
fetch_track
(
username
,
map
)
text
=
format_now_playing
(
map
,
track
)
user
=
if
account
=
Nola.Account
.
get
(
id_or_user
)
do
user
=
Nola.UserTrack
.
find_by_account
(
message
.
network
,
account
)
if
(
user
,
do
:
user
.
nick
,
else
:
account
.
name
)
else
username
end
if
user
&&
text
do
message
.
replyfun
.
(
"
#{
user
}
#{
text
}
"
)
else
message
.
replyfun
.
(
"
#{
username
}
: pas de résultat"
)
end
other
->
message
.
replyfun
.
(
"erreur :("
)
end
end
defp
now_playing
(
user
)
do
api
=
Application
.
get_env
(
:nola
,
:lastfm
)[
:api_key
]
url
=
"http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&extended=1"
<>
"&api_key="
<>
api
<>
"&user="
<>
user
case
HTTPoison
.
get
(
url
)
do
{
:ok
,
%
HTTPoison.Response
{
status_code
:
200
,
body
:
body
}}
->
Jason
.
decode
(
body
)
{
:ok
,
%
HTTPoison.Response
{
status_code
:
404
}}
->
{
:error
,
"last.fm: utilisateur \"
#{
user
}
\" inexistant"
}
{
:ok
,
%
HTTPoison.Response
{
status_code
:
code
}}
->
{
:error
,
"last.fm: erreur
#{
to_string
(
code
)
}
"
}
error
->
Logger
.
error
"Lastfm http error:
#{
inspect
error
}
"
:error
end
end
defp
fetch_track
(
user
,
%{
"recenttracks"
=>
%{
"track"
=>
[
t
=
%{
"name"
=>
name
,
"artist"
=>
%{
"name"
=>
artist
}}
|
_
]}})
do
api
=
Application
.
get_env
(
:nola
,
:lastfm
)[
:api_key
]
url
=
"http://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json"
<>
"&api_key="
<>
api
<>
"&username="
<>
user
<>
"&artist="
<>
URI
.
encode
(
artist
)
<>
"&track="
<>
URI
.
encode
(
name
)
case
HTTPoison
.
get
(
url
)
do
{
:ok
,
%
HTTPoison.Response
{
status_code
:
200
,
body
:
body
}}
->
case
Jason
.
decode
(
body
)
do
{
:ok
,
body
}
->
body
[
"track"
]
||
%{}
_
->
%{}
end
error
->
Logger
.
error
"Lastfm http error:
#{
inspect
error
}
"
:error
end
end
defp
format_now_playing
(%{
"recenttracks"
=>
%{
"track"
=>
[
track
=
%{
"@attr"
=>
%{
"nowplaying"
=>
"true"
}}
|
_
]}},
et
)
do
format_track
(
true
,
track
,
et
)
end
defp
format_now_playing
(%{
"recenttracks"
=>
%{
"track"
=>
[
track
|
_
]}},
et
)
do
format_track
(
false
,
track
,
et
)
end
defp
format_now_playing
(%{
"error"
=>
err
,
"message"
=>
message
},
_
)
do
"last.fm error
#{
err
}
:
#{
message
}
"
end
defp
format_now_playing
(
miss
)
do
nil
end
defp
format_track
(
np
,
track
,
extended
)
do
artist
=
track
[
"artist"
][
"name"
]
album
=
if
track
[
"album"
][
"
#
text"
],
do
:
" ("
<>
track
[
"album"
][
"
#
text"
]
<>
")"
,
else
:
""
name
=
track
[
"name"
]
<>
album
action
=
if
np
,
do
:
"écoute "
,
else
:
"a écouté"
love
=
if
track
[
"loved"
]
!=
"0"
,
do
:
"❤️"
count
=
if
x
=
extended
[
"userplaycount"
],
do
:
"x
#{
x
}
#{
love
}
"
tags
=
(
get_in
(
extended
,
[
"toptags"
,
"tag"
])
||
[])
|>
Enum
.
map
(
fn
(
tag
)
->
tag
[
"name"
]
end
)
|>
Enum
.
filter
(
&
&1
)
|>
Enum
.
join
(
", "
)
[
action
,
artist
,
name
,
count
,
tags
,
track
[
"url"
]]
|>
Enum
.
filter
(
&
&1
)
|>
Enum
.
map
(
&
String
.
trim
(
&1
))
|>
Enum
.
join
(
" - "
)
end
end
File Metadata
Details
Attached
Mime Type
text/x-ruby
Expires
Mon, Jul 7, 1:18 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
49900
Default Alt Text
last_fm.ex (6 KB)
Attached To
rNOLA Nola
Event Timeline
Log In to Comment