defmodule LSG.IRC.AlcologPlugin do require Logger @moduledoc """ # alcoolisme _(v2)_ * **`!santai [annotation]`** enregistre un nouveau verre de `montant` d'une boisson à `degrés d'alcool`. * **!`` `[coeff]` `[annotation]`** enregistre de l'alcoolisme. * **!alcoolisme `[pseudo]`** affiche les points d'alcoolisme. Triggers/Coeffs: * bière: (coeffs: 25, 50/+, 75/++, 100/+++, ++++) * pinard: (coeffs: +, ++, +++, ++++) * shot/fort/whisky/rhum/..: (coeffs: +, ++, +++, ++++) * eau (-1) Annotation: champ libre! """ @triggers %{ "apero" => %{ triggers: ["apero", "apéro", "apairo", "santai"], default_coeff: "25", coeffs: %{ "+" => 2, "++" => 3, "+++" => 4, "++++" => 5, } }, "bière" => %{ triggers: ["beer", "bière", "biere", "biaire"], default_coeff: "25", coeffs: %{ "25" => 1, "50" => 2, "75" => 3, "100" => 4, "+" => 2, "++" => 3, "+++" => 4, "++++" => 5, } }, "pinard" => %{ triggers: ["pinard", "vin", "rouge", "blanc", "rosé", "rose"], annotations: ["rouge", "blanc", "rosé", "rose"], default_coeff: "", coeffs: %{ "" => 1, "+" => 2, "++" => 3, "+++" => 4, "++++" => 5, "vase" => 6, } }, "fort" => %{ triggers: ["shot", "royaume", "whisky", "rhum", "armagnac", "dijo"], default_coeff: "", coeffs: %{ "" => 3, "+" => 5, "++" => 7, "+++" => 9, "++++" => 11 } }, "eau" => %{ triggers: ["eau"], default_coeff: "1", coeffs: %{ "1" => -2, "+" => -3, "++" => -4, "+++" => -6, "++++" => -8 } } } @santai ["SANTÉ", "SANTÉ", "SANTAIIII", "SANTAIIIIIIIIII", "SANTAI", "A LA TIENNE"] def irc_doc, do: @moduledoc def start_link(), do: GenServer.start_link(__MODULE__, []) def init(_) do {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcoolisme", []) for {_, config} <- @triggers do for trigger <- config.triggers do {:ok, _} = Registry.register(IRC.PubSub, "trigger:#{trigger}", []) for coeff when byte_size(coeff) > 0 <- Map.keys(config.coeffs) do {:ok, _} = Registry.register(IRC.PubSub, "trigger:#{trigger}#{coeff}", []) end end end dets_filename = (LSG.data_path() <> "/" <> "alcoolisme.dets") |> String.to_charlist {:ok, dets} = :dets.open_file(dets_filename, [{:type,:bag}]) {:ok, dets} end for {name, config} <- @triggers do coeffs = Map.get(config, "coeffs") default_coeff_value = Map.get(config.coeffs, config.default_coeff) IO.puts "at triggers #{inspect config}" # Handle each trigger for trigger <- config.triggers do # … with a known coeff … for {coef, value} when byte_size(coef) > 0 <- config.coeffs do def handle_info({:irc, :trigger, unquote(trigger), m = %IRC.Message{trigger: %IRC.Trigger{args: [unquote(coef)<>_ | args], type: :bang}}}, dets) do handle_bang(unquote(name), unquote(value), m, args, dets) {:noreply, dets} end def handle_info({:irc, :trigger, unquote(trigger)<>unquote(coef), m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, dets) do handle_bang(unquote(name), unquote(value), m, args, dets) {:noreply, dets} end end # … or without def handle_info({:irc, :trigger, unquote(trigger), m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, dets) do handle_bang(unquote(name), unquote(default_coeff_value), m, args, dets) {:noreply, dets} end end end def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, dets) do nick = case args do [nick] -> nick [] -> m.sender.nick end case get_statistics_for_nick(dets, nick) do {count, {_, last_at, last_points, last_type, last_descr}} -> m.replyfun.("#{nick} a #{count} points d'alcoolisme. Dernier verre: #{present_type(last_type, last_descr)} [#{last_points}] #{format_relative_timestamp(last_at)}") _ -> m.replyfun.("honteux mais #{nick} n'a pas l'air alcoolique du tout. /kick") end {:noreply, dets} end defp handle_bang(name, points, message, args, dets) do description = case args do [] -> nil [something] -> something something when is_list(something) -> Enum.join(something, " ") _ -> nil end now = DateTime.to_unix(DateTime.utc_now(), :milliseconds) :ok = :dets.insert(dets, {String.downcase(message.sender.nick), now, points, name, description}) {count, {_, last_at, last_points, last_type, last_descr}} = get_statistics_for_nick(dets, message.sender.nick) sante = @santai |> Enum.shuffle() |> Enum.random() message.replyfun.("#{sante} #{message.sender.nick} #{format_points(points)}! (total #{count} points)") end defp get_statistics_for_nick(dets, nick) do qvc = :dets.lookup(dets, String.downcase(nick)) IO.puts inspect(qvc) count = Enum.reduce(qvc, 0, fn({_nick, _ts, points, _type, _descr}, acc) -> acc + points end) last = List.last(qvc) || nil {count, last} end def present_type(type, descr) when descr in [nil, ""], do: "#{type}" def present_type(type, description), do: "#{type} (#{description})" def format_points(int) when int > 0 do "+#{Integer.to_string(int)}" end def format_points(int) when int < 0 do Integer.to_string(int) end def format_points(0), do: "0" defp format_relative_timestamp(timestamp) do alias Timex.Format.DateTime.Formatters alias Timex.Timezone date = timestamp |> DateTime.from_unix!(:milliseconds) |> Timezone.convert("Europe/Paris") {:ok, relative} = Formatters.Relative.relative_to(date, Timex.now("Europe/Paris"), "{relative}", "fr") {:ok, detail} = Formatters.Default.lformat(date, " ({h24}:{m})", "fr") relative <> detail end end