diff options
-rw-r--r-- | lib/plugins/preums.ex | 146 |
1 files changed, 91 insertions, 55 deletions
diff --git a/lib/plugins/preums.ex b/lib/plugins/preums.ex index 83d99cd..ac5da20 100644 --- a/lib/plugins/preums.ex +++ b/lib/plugins/preums.ex @@ -42,40 +42,44 @@ defmodule Nola.Plugins.Preums do # dets {{chan, day = {yyyy, mm, dd}}, nick, now, perfect?, text} def all(dets) do - :dets.foldl(fn(i, acc) -> [i|acc] end, [], dets) + :dets.foldl(fn i, acc -> [i | acc] end, [], dets) end def all(dets, channel) do - fun = fn({{chan, date}, account_id, time, perfect, text}, acc) -> + fun = fn {{chan, date}, account_id, time, perfect, text}, acc -> if channel == chan do [%{date: date, account_id: account_id, time: time, perfect: perfect, text: text} | acc] else acc end end + :dets.foldl(fun, [], dets) end def topnicks(dets, channel, options \\ []) do - sort_elem = case Keyword.get(options, :sort_by, :score) do - :score -> 1 - :count -> 0 - end + sort_elem = + case Keyword.get(options, :sort_by, :score) do + :score -> 1 + :count -> 0 + end - fun = fn(x = {{chan, date}, account_id, time, perfect, text}, acc) -> - if (channel == nil and chan) or (channel == chan) do + fun = fn x = {{chan, date}, account_id, time, perfect, text}, acc -> + if (channel == nil and chan) or channel == chan do + incr_points = if NaiveDateTime.utc_now().year == time.year, do: 1, else: 0 {count, points} = Map.get(acc, account_id, {0, 0}) - score = score(chan, account_id, time, perfect, text) - Map.put(acc, account_id, {count + 1, points + score}) + Map.put(acc, account_id, {count + 1, points + incr_points}) else acc end end + :dets.foldl(fun, %{}, dets) - |> Enum.sort_by(fn({_account_id, value}) -> elem(value, sort_elem) end, &>=/2) + |> Enum.sort_by(fn {_account_id, value} -> elem(value, sort_elem) end, &>=/2) end def irc_doc, do: @moduledoc + def start_link() do GenServer.start_link(__MODULE__, [], name: __MODULE__) end @@ -90,39 +94,51 @@ defmodule Nola.Plugins.Preums do {:ok, _} = Registry.register(Nola.PubSub, "messages", regopts) {:ok, _} = Registry.register(Nola.PubSub, "triggers", regopts) {:ok, dets} = :dets.open_file(dets(), [{:repair, :force}]) - Util.ets_mutate_select_each(:dets, dets, [{:"$1", [], [:"$1"]}], fn(table, obj) -> + + Util.ets_mutate_select_each(:dets, dets, [{:"$1", [], [:"$1"]}], fn table, obj -> {key, nick, now, perfect, text} = obj + case key do - {{net, {bork,chan}}, date} -> + {{net, {bork, chan}}, date} -> :dets.delete(table, key) - nick = if Nola.Account.get(nick) do - nick - else - if acct = Nola.Account.find_always_by_nick(net, nil, nick) do - acct.id - else + + nick = + if Nola.Account.get(nick) do nick + else + if acct = Nola.Account.find_always_by_nick(net, nil, nick) do + acct.id + else + nick + end end - end - :dets.insert(table, { { {net,chan}, date }, nick, now, perfect, text}) + + :dets.insert(table, {{{net, chan}, date}, nick, now, perfect, text}) + {{_net, nil}, _} -> :dets.delete(table, key) + {{net, chan}, date} -> if !Nola.Account.get(nick) do if acct = Nola.Account.find_always_by_nick(net, chan, nick) do :dets.delete(table, key) - :dets.insert(table, { { {net,chan}, date }, acct.id, now, perfect, text}) + :dets.insert(table, {{{net, chan}, date}, acct.id, now, perfect, text}) end end + _ -> - Logger.debug("DID NOT FIX: #{inspect key}") + Logger.debug("DID NOT FIX: #{inspect(key)}") end end) + {:ok, %{dets: dets}} end # Latest - def handle_info({:irc, :trigger, "preums", m = %Nola.Message{trigger: %Nola.Trigger{type: :bang}}}, state) do + def handle_info( + {:irc, :trigger, "preums", m = %Nola.Message{trigger: %Nola.Trigger{type: :bang}}}, + state + ) do channelkey = {m.network, m.channel} state = handle_preums(m, state) tz = timezone(channelkey) @@ -130,14 +146,16 @@ defmodule Nola.Plugins.Preums do date = {now.year, now.month, now.day} key = {channelkey, date} chan_cache = Map.get(state, channelkey, %{}) - item = if i = Map.get(chan_cache, date) do - i - else - case :dets.lookup(state.dets, key) do - [item = {^key, _account_id, _now, _perfect, _text}] -> item - _ -> nil + + item = + if i = Map.get(chan_cache, date) do + i + else + case :dets.lookup(state.dets, key) do + [item = {^key, _account_id, _now, _perfect, _text}] -> item + _ -> nil + end end - end if item do {_, account_id, date, _perfect, text} = item @@ -147,33 +165,45 @@ defmodule Nola.Plugins.Preums do nick = if(user, do: user.nick, else: account.name) m.replyfun.("preums: #{nick} à #{h}: “#{text}”") end + {:noreply, state} end # Stats - def handle_info({:irc, :trigger, "preums", m = %Nola.Message{trigger: %Nola.Trigger{type: :dot}}}, state) do + def handle_info( + {:irc, :trigger, "preums", m = %Nola.Message{trigger: %Nola.Trigger{type: :dot}}}, + state + ) do channel = {m.network, m.channel} state = handle_preums(m, state) - top = topnicks(state.dets, channel, sort_by: :score) - |> Enum.map(fn({account_id, {count, score}}) -> - account = Nola.Account.get(account_id) - user = Nola.UserTrack.find_by_account(m.network, account) - nick = if(user, do: user.nick, else: account.name) - "#{nick}: #{score} (#{count})" - end) - |> Enum.intersperse(", ") - |> Enum.join("") - msg = unless top == "" do - "top preums: #{top}" - else - "vous êtes tous nuls" - end + + top = + topnicks(state.dets, channel, sort_by: :score) + |> Enum.map(fn {account_id, {count, score}} -> + account = Nola.Account.get(account_id) + user = Nola.UserTrack.find_by_account(m.network, account) + nick = if(user, do: user.nick, else: account.name) + "#{nick}: #{score} (#{count})" + end) + |> Enum.intersperse(", ") + |> Enum.join("") + + msg = + unless top == "" do + "top preums: #{top}" + else + "vous êtes tous nuls" + end + m.replyfun.(msg) {:noreply, state} end # Help - def handle_info({:irc, :trigger, "preums", m = %Nola.Message{trigger: %Nola.Trigger{type: :query}}}, state) do + def handle_info( + {:irc, :trigger, "preums", m = %Nola.Message{trigger: %Nola.Trigger{type: :query}}}, + state + ) do state = handle_preums(m, state) msg = "!preums - preums du jour, .preums top preumseurs" m.replymsg.(msg) @@ -194,27 +224,33 @@ defmodule Nola.Plugins.Preums do # Account def handle_info({:account_change, old_id, new_id}, state) do spec = [{{:_, :"$1", :_, :_, :_}, [{:==, :"$1", {:const, old_id}}], [:"$_"]}] - Util.ets_mutate_select_each(:dets, state.dets, spec, fn(table, obj) -> + + Util.ets_mutate_select_each(:dets, state.dets, spec, fn table, obj -> rename_object_owner(table, obj, new_id) end) + {:noreply, state} end # Account: move from nick to account id # FIXME: Doesn't seem to work. def handle_info({:accounts, accounts}, state) do - for x={:account, _net, _chan, _nick, _account_id} <- accounts do + for x = {:account, _net, _chan, _nick, _account_id} <- accounts do handle_info(x, state) end + {:noreply, state} end + def handle_info({:account, _net, _chan, nick, account_id}, state) do nick = String.downcase(nick) spec = [{{:_, :"$1", :_, :_, :_}, [{:==, :"$1", {:const, nick}}], [:"$_"]}] - Util.ets_mutate_select_each(:dets, state.dets, spec, fn(table, obj) -> + + Util.ets_mutate_select_each(:dets, state.dets, spec, fn table, obj -> Logger.debug("account:: merging #{nick} -> #{account_id}") rename_object_owner(table, obj, account_id) end) + {:noreply, state} end @@ -222,7 +258,6 @@ defmodule Nola.Plugins.Preums do {:noreply, dets} end - defp rename_object_owner(table, object = {key, _, now, perfect, time}, new_id) do :dets.delete_object(table, key) :dets.insert(table, {key, new_id, now, perfect, time}) @@ -247,20 +282,23 @@ defmodule Nola.Plugins.Preums do date = {now.year, now.month, now.day} key = {channel, date} chan_cache = Map.get(state, channel, %{}) + unless i = Map.get(chan_cache, date) do case :dets.lookup(state.dets, key) do [item = {^key, _nick, _now, _perfect, _text}] -> # Preums lost, but wasn't cached Map.put(state, channel, %{date => item}) + [] -> # Preums won! - perfect? = Enum.any?(@perfects, fn(perfect) -> Regex.match?(perfect, text) end) + perfect? = Enum.any?(@perfects, fn perfect -> Regex.match?(perfect, text) end) item = {key, m.account.id, now, perfect?, text} :dets.insert(state.dets, item) :dets.sync(state.dets) Map.put(state, channel, %{date => item}) + {:error, _} = error -> - Logger.error("#{__MODULE__} dets lookup failed: #{inspect error}") + Logger.error("#{__MODULE__} dets lookup failed: #{inspect(error)}") state end else @@ -271,6 +309,4 @@ defmodule Nola.Plugins.Preums do def score(_chan, _account, _time, _perfect, _text) do 1 end - - end |