summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/last_fm_handler.ex
diff options
context:
space:
mode:
authorhref <href@random.sh>2018-02-10 21:40:22 +0100
committerhref <href@random.sh>2018-02-10 21:40:22 +0100
commit935a36eecc0faea60236101e11bc9f7cf1872686 (patch)
treeb7b4358dee2eb3fc60681852f62c750ae8c05cb9 /lib/lsg_irc/last_fm_handler.ex
parentsse / embedded player (diff)
update
Diffstat (limited to 'lib/lsg_irc/last_fm_handler.ex')
-rw-r--r--lib/lsg_irc/last_fm_handler.ex138
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