summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/last_fm_plugin.ex
diff options
context:
space:
mode:
authorhref <href@random.sh>2020-03-11 21:18:34 +0100
committerhref <href@random.sh>2020-03-11 21:18:34 +0100
commita28d24470ddeca6196219a1333c1ccac1319efef (patch)
tree4f29e3c8fb6afbb1f99d6b8737f844c95fca54df /lib/lsg_irc/last_fm_plugin.ex
parentup to 420*100 (diff)
welp
Diffstat (limited to 'lib/lsg_irc/last_fm_plugin.ex')
-rw-r--r--lib/lsg_irc/last_fm_plugin.ex145
1 files changed, 145 insertions, 0 deletions
diff --git a/lib/lsg_irc/last_fm_plugin.ex b/lib/lsg_irc/last_fm_plugin.ex
new file mode 100644
index 0000000..2446473
--- /dev/null
+++ b/lib/lsg_irc/last_fm_plugin.ex
@@ -0,0 +1,145 @@
+defmodule LSG.IRC.LastFmPlugin do
+ require Logger
+
+ @moduledoc """
+ # last.fm
+
+ * **!lastfm `[nick|username]`**
+ * **!lastfmall**
+ * **+lastfm `<username last.fm>`, -lastfm**
+ """
+
+ defstruct dets: nil
+
+ def irc_doc, do: @moduledoc
+
+ def start_link() do
+ GenServer.start_link(__MODULE__, [])
+ end
+
+ def init([]) do
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:lastfm", [])
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:lastfmall", [])
+ dets_filename = (LSG.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, {String.downcase(message.sender.nick), 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.sender.nick) do
+ [{_nick, username}] ->
+ :dets.delete(state.dets, String.downcase(message.sender.nick))
+ 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: :bang, args: []}}}, state) do
+ irc_now_playing(message.sender.nick, message, state)
+ {:noreply, state}
+ end
+
+ def handle_info({:irc, :trigger, "lastfm", 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, "lastfmall", message = %{trigger: %{type: :bang}}}, 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, 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)
+ username = case :dets.lookup(state.dets, String.downcase(nick_or_user)) do
+ [{^nick_or_user, username}] -> username
+ _ -> nick_or_user
+ end
+
+ case now_playing(username) do
+ {:error, text} when is_binary(text) ->
+ message.replyfun.(text)
+ {:ok, map} when is_map(map) ->
+ text = format_now_playing(map)
+ user = lookup_nick(username, state)
+ if user && text do
+ message.replyfun.("#{user} #{text}")
+ else
+ message.replyfun.("#{username}: pas de résultat")
+ end
+ other ->
+ message.replyfun.("erreur http")
+ end
+ end
+
+ defp now_playing(user) do
+ api = Application.get_env(:lsg, :lastfm)[: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