diff options
author | href <href@random.sh> | 2020-03-11 21:18:34 +0100 |
---|---|---|
committer | href <href@random.sh> | 2020-03-11 21:18:34 +0100 |
commit | a28d24470ddeca6196219a1333c1ccac1319efef (patch) | |
tree | 4f29e3c8fb6afbb1f99d6b8737f844c95fca54df /lib/lsg_irc/last_fm_plugin.ex | |
parent | up to 420*100 (diff) |
welp
Diffstat (limited to 'lib/lsg_irc/last_fm_plugin.ex')
-rw-r--r-- | lib/lsg_irc/last_fm_plugin.ex | 145 |
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 |