diff options
Diffstat (limited to 'lib/plugins/quatre_cent_vingt.ex')
-rw-r--r-- | lib/plugins/quatre_cent_vingt.ex | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/lib/plugins/quatre_cent_vingt.ex b/lib/plugins/quatre_cent_vingt.ex new file mode 100644 index 0000000..3331625 --- /dev/null +++ b/lib/plugins/quatre_cent_vingt.ex @@ -0,0 +1,149 @@ +defmodule Nola.Plugins.QuatreCentVingt do + require Logger + + @moduledoc """ + # 420 + + * **!420**: recorde un nouveau 420. + * **!420*x**: recorde un nouveau 420*x (*2 = 840, ...) (à vous de faire la multiplication). + * **!420 pseudo**: stats du pseudo. + """ + + @achievements %{ + 1 => ["[le premier… il faut bien commencer un jour]"], + 10 => ["T'en es seulement à 10 ? ╭∩╮(Ο_Ο)╭∩╮"], + 42 => ["Bravo, et est-ce que autant de pétards t'on aidés à trouver la Réponse ? ٩(- ̮̮̃-̃)۶ [42]"], + 100 => ["°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸ 100 °º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸"], + 115 => [" ۜ\(סּںסּَ` )/ۜ 115!!"] + } + + @emojis [ + "\\o/", + "~o~", + "~~o∞~~", + "*\\o/*", + "**\\o/**", + "*ô*", + ] + + @coeffs Range.new(1, 100) + + def irc_doc, do: @moduledoc + + def start_link, do: GenServer.start_link(__MODULE__, [], name: __MODULE__) + + def init(_) do + for coeff <- @coeffs do + {:ok, _} = Registry.register(IRC.PubSub, "trigger:#{420*coeff}", [plugin: __MODULE__]) + end + {:ok, _} = Registry.register(IRC.PubSub, "account", [plugin: __MODULE__]) + dets_filename = (Nola.data_path() <> "/420.dets") |> String.to_charlist + {:ok, dets} = :dets.open_file(dets_filename, [{:type,:bag},{:repair,:force}]) + {:ok, dets} + :ignore + end + + for coeff <- @coeffs do + qvc = to_string(420 * coeff) + def handle_info({:irc, :trigger, unquote(qvc), m = %IRC.Message{trigger: %IRC.Trigger{args: [], type: :bang}}}, dets) do + {count, last} = get_statistics_for_nick(dets, m.account.id) + count = count + unquote(coeff) + text = achievement_text(count) + now = DateTime.to_unix(DateTime.utc_now())-1 # this is ugly + for i <- Range.new(1, unquote(coeff)) do + :ok = :dets.insert(dets, {m.account.id, now+i}) + end + last_s = if last do + last_s = format_relative_timestamp(last) + " (le dernier était #{last_s})" + else + "" + end + m.replyfun.("#{m.sender.nick} 420 +#{unquote(coeff)} #{text}#{last_s}") + {:noreply, dets} + end + end + + def handle_info({:irc, :trigger, "420", m = %IRC.Message{trigger: %IRC.Trigger{args: [nick], type: :bang}}}, dets) do + account = IRC.Account.find_by_nick(m.network, nick) + if account do + text = case get_statistics_for_nick(dets, m.account.id) do + {0, _} -> "#{nick} n'a jamais !420 ... honte à lui." + {count, last} -> + last_s = format_relative_timestamp(last) + "#{nick} 420: total #{count}, le dernier #{last_s}" + end + m.replyfun.(text) + else + m.replyfun.("je connais pas de #{nick}") + end + {:noreply, dets} + end + + # Account + def handle_info({:account_change, old_id, new_id}, dets) do + spec = [{{:"$1", :_}, [{:==, :"$1", {:const, old_id}}], [:"$_"]}] + Util.ets_mutate_select_each(:dets, dets, spec, fn(table, obj) -> + rename_object_owner(table, obj, new_id) + end) + {:noreply, dets} + end + + # Account: move from nick to account id + def handle_info({:accounts, accounts}, dets) do + for x={:account, _net, _chan, _nick, _account_id} <- accounts do + handle_info(x, dets) + end + {:noreply, dets} + end + def handle_info({:account, _net, _chan, nick, account_id}, dets) do + nick = String.downcase(nick) + spec = [{{:"$1", :_}, [{:==, :"$1", {:const, nick}}], [:"$_"]}] + Util.ets_mutate_select_each(:dets, dets, spec, fn(table, obj) -> + Logger.debug("account:: merging #{nick} -> #{account_id}") + rename_object_owner(table, obj, account_id) + end) + {:noreply, dets} + end + + def handle_info(_, dets) do + {:noreply, dets} + end + + defp rename_object_owner(table, object = {_, at}, account_id) do + :dets.delete_object(table, object) + :dets.insert(table, {account_id, at}) + end + + + defp format_relative_timestamp(timestamp) do + alias Timex.Format.DateTime.Formatters + alias Timex.Timezone + date = timestamp + |> DateTime.from_unix! + |> 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 + + defp get_statistics_for_nick(dets, acct) do + qvc = :dets.lookup(dets, acct) |> Enum.sort + count = Enum.reduce(qvc, 0, fn(_, acc) -> acc + 1 end) + {_, last} = List.last(qvc) || {nil, nil} + {count, last} + end + + @achievements_keys Map.keys(@achievements) + defp achievement_text(count) when count in @achievements_keys do + Enum.random(Map.get(@achievements, count)) + end + + defp achievement_text(count) do + emoji = Enum.random(@emojis) + "#{emoji} [#{count}]" + end + +end |