diff options
author | href <href@random.sh> | 2018-02-10 21:40:22 +0100 |
---|---|---|
committer | href <href@random.sh> | 2018-02-10 21:40:22 +0100 |
commit | 935a36eecc0faea60236101e11bc9f7cf1872686 (patch) | |
tree | b7b4358dee2eb3fc60681852f62c750ae8c05cb9 /lib/lsg_irc/last_fm_handler.ex | |
parent | sse / embedded player (diff) |
update
Diffstat (limited to 'lib/lsg_irc/last_fm_handler.ex')
-rw-r--r-- | lib/lsg_irc/last_fm_handler.ex | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/lib/lsg_irc/last_fm_handler.ex b/lib/lsg_irc/last_fm_handler.ex new file mode 100644 index 0000000..ad6dae9 --- /dev/null +++ b/lib/lsg_irc/last_fm_handler.ex @@ -0,0 +1,138 @@ +defmodule LSG.IRC.LastFmHandler do + require Logger + + @moduledoc """ + # last.fm + + !lastfm [nick|username] + say what nick/specified username is listening on lastfm; if last.fm username is known (via +lastfm). + !lastfmall + say what known users (+lastfm) are listening + +lastfm <username> + links the nick who use the command to <username> last.fm account. + -lastfm + unlinks the nick's previously set last.fm username. + """ + + defstruct client: nil, dets: nil + + def irc_doc, do: @moduledoc + + def start_link(client) do + GenServer.start_link(__MODULE__, [client]) + end + + def init([client]) do + ExIRC.Client.add_handler(client, self()) + dets_filename = Application.get_env(:lsg, __MODULE__)[:dets_path] + {:ok, dets} = :dets.open_file(dets_filename, []) + {:ok, %__MODULE__{client: client, dets: dets}} + end + + def handle_info({:received, "+lastfm " <> username, sender, chan}, state) do + username = String.strip(username) + :ok = :dets.insert(state.dets, {String.downcase(sender.nick), username}) + ExIRC.Client.msg(state.client, :privmsg, chan, "#{sender.nick}: nom d'utilisateur last.fm configuré: \"#{username}\"") + {:noreply, state} + end + + def handle_info({:received, "-lastfm", sender, chan}, state) do + text = case :dets.lookup(state.dets, sender.nick) do + [{_nick, username}] -> + :dets.delete(state.dets, sender.nick) + "#{sender.nick}: nom d'utilisateur last.fm enlevé" + _ -> "" + end + ExIRC.Client.msg(state.client, :privmsg, chan, text) + {:noreply, state} + end + + def handle_info({:received, "!lastfm", sender, chan}, state) do + irc_now_playing(sender.nick, chan, state) + {:noreply, state} + end + + def handle_info({:received, "!lastfm " <> nick_or_user, sender, chan}, state) do + irc_now_playing(nick_or_user, chan, state) + {:noreply, state} + end + + def handle_info({:received, "!lastfmall", sender, chan}, state) do + foldfun = fn({_nick, user}, acc) -> [user|acc] end + usernames = :dets.foldl(foldfun, [], state.dets) + |> Enum.uniq + for u <- usernames, do: irc_now_playing(u, chan, state) + {:noreply, state} + end + + def handle_info(info, state) do + {:noreply, state} + end + + defp irc_now_playing(nick_or_user, chan, state) do + nick_or_user = String.strip(nick_or_user) + username = case :dets.lookup(state.dets, nick_or_user) do + [{^nick_or_user, username}] -> username + _ -> nick_or_user + end + + case now_playing(username) do + {:error, text} when is_binary(text) -> ExIRC.Client.msg(state.client, :privmsg, chan, text) + {:ok, map} when is_map(map) -> + text = format_now_playing(map) + user = lookup_nick(username, state) + if user && text, do: ExIRC.Client.msg(state.client, :privmsg, chan, "#{user} #{text}") + other -> + IO.inspect(other) + nil + end + end + + defp now_playing(user) do + api = Application.get_env(:lsg, __MODULE__)[:api_key] + url = "http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=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: 400}} -> {: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 format_now_playing(%{"recenttracks" => %{"track" => [track = %{"@attr" => %{"nowplaying" => "true"}}, _old]}}) do + format_track(true, track) + end + + defp format_now_playing(%{"recenttracks" => %{"track" => [track]}}) do + format_track(false, track) + 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) do + album = if track["album"]["#text"] do + " (" <> track["album"]["#text"] <> ")" + else + "" + end + action = if np, do: "écoute ", else: "a écouté " + action <> track["artist"]["#text"] <> " - " <> track["name"] <> album <> " — " <> track["url"] + end + + defp lookup_nick(username, state) do + case :dets.match(state.dets, {:'$1', username}) do + [[match]] -> match + [[match] | _many] -> match + _ -> username + end + end + +end |