summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/preums_plugin.ex
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/lsg_irc/preums_plugin.ex150
1 files changed, 136 insertions, 14 deletions
diff --git a/lib/lsg_irc/preums_plugin.ex b/lib/lsg_irc/preums_plugin.ex
index 98cd539..1f9a76b 100644
--- a/lib/lsg_irc/preums_plugin.ex
+++ b/lib/lsg_irc/preums_plugin.ex
@@ -6,31 +6,94 @@ defmodule LSG.IRC.PreumsPlugin do
* `.preums`: stats des preums
"""
+ require Logger
+
@perfects [~r/preum(s|)/i]
# dets {{chan, day = {yyyy, mm, dd}}, nick, now, perfect?, text}
+ def all(dets) do
+ :dets.foldl(fn(i, acc) -> [i|acc] end, [], dets)
+ end
+
+ def all(dets, channel) do
+ fun = fn({{chan, date}, nick, time, perfect, text}, acc) ->
+ if channel == chan do
+ [%{date: date, nick: nick, time: time, perfect: perfect, text: text} | acc]
+ else
+ acc
+ end
+ end
+ :dets.foldl(fun, [], dets)
+ end
+
+ def topnicks(dets, channel) do
+ fun = fn(x = {{chan, date}, nick, _time, _perfect, _text}, acc) ->
+ if (channel == nil and chan) or (channel == chan) do
+ count = Map.get(acc, nick, 0)
+ Map.put(acc, nick, count + 1)
+ else
+ acc
+ end
+ end
+ :dets.foldl(fun, %{}, dets)
+ |> Enum.sort_by(fn({nick, count}) -> count end, &>=/2)
+ end
+
def irc_doc, do: @moduledoc
def start_link() do
GenServer.start_link(__MODULE__, [])
end
+ def dets do
+ (LSG.data_path() <> "/preums.dets") |> String.to_charlist()
+ end
+
def init([]) do
+ {:ok, _} = Registry.register(IRC.PubSub, "account", [])
{:ok, _} = Registry.register(IRC.PubSub, "message", [])
{:ok, _} = Registry.register(IRC.PubSub, "triggers", [])
- dets_filename = (LSG.data_path() <> "/preums.dets") |> String.to_charlist()
- {:ok, dets} = :dets.open_file(dets_filename, [])
+ {:ok, dets} = :dets.open_file(dets(), [{:repair, :force}])
+ 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} ->
+ :dets.delete(table, key)
+ nick = if IRC.Account.get(nick) do
+ nick
+ else
+ if acct = IRC.Account.find_always_by_nick(net, nil, nick) do
+ acct.id
+ else
+ nick
+ end
+ end
+ :dets.insert(table, { { {net,chan}, date }, nick, now, perfect, text})
+ {{_net, nil}, _} ->
+ :dets.delete(table, key)
+ {{net, chan}, date} ->
+ if !IRC.Account.get(nick) do
+ if acct = IRC.Account.find_always_by_nick(net, chan, nick) do
+ :dets.delete(table, key)
+ :dets.insert(table, { { {net,chan}, date }, acct.id, now, perfect, text})
+ end
+ end
+ _ ->
+ Logger.debug("DID NOT FIX: #{inspect key}")
+ end
+ end)
{:ok, %{dets: dets}}
end
# Latest
- def handle_info({:irc, :trigger, "preums", m = %IRC.Message{channel: channel, trigger: %IRC.Trigger{type: :bang}}}, state) do
+ def handle_info({:irc, :trigger, "preums", m = %IRC.Message{trigger: %IRC.Trigger{type: :bang}}}, state) do
+ channelkey = {m.network, m.channel}
state = handle_preums(m, state)
- tz = timezone(channel)
+ tz = timezone(channelkey)
{:ok, now} = DateTime.now(tz, Tzdata.TimeZoneDatabase)
date = {now.year, now.month, now.day}
- key = {channel, date}
- chan_cache = Map.get(state, channel, %{})
+ key = {channelkey, date}
+ chan_cache = Map.get(state, channelkey, %{})
item = if i = Map.get(chan_cache, date) do
i
else
@@ -49,14 +112,30 @@ defmodule LSG.IRC.PreumsPlugin do
end
# Stats
- def handle_info({:irc, :trigger, "preums", m = %IRC.Message{channel: channel, trigger: %IRC.Trigger{type: :dot}}}, state) do
+ def handle_info({:irc, :trigger, "preums", m = %IRC.Message{trigger: %IRC.Trigger{type: :dot}}}, state) do
+ channel = {m.network, m.channel}
state = handle_preums(m, state)
+ top = topnicks(state.dets, channel)
+ |> Enum.map(fn({nick, count}) ->
+ "#{nick} (#{count})"
+ end)
+ |> Enum.filter(fn(x) -> x 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 = %IRC.Message{channel: channel, trigger: %IRC.Trigger{type: :query}}}, state) do
+ def handle_info({:irc, :trigger, "preums", m = %IRC.Message{trigger: %IRC.Trigger{type: :query}}}, state) do
state = handle_preums(m, state)
+ msg = "!preums - preums du jour, .preums top preumseurs"
+ m.replymsg.(msg)
{:noreply, state}
end
@@ -71,6 +150,43 @@ defmodule LSG.IRC.PreumsPlugin do
{:noreply, handle_preums(m, state)}
end
+ # 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) ->
+ 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
+ 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) ->
+ Logger.debug("account:: merging #{nick} -> #{account_id}")
+ rename_object_owner(table, obj, account_id)
+ end)
+ {:noreply, state}
+ end
+
+ def handle_info(_, dets) 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})
+ end
+
defp timezone(channel) do
env = Application.get_env(:lsg, LSG.IRC.PreumsPlugin, [])
channels = Keyword.get(env, :channels, %{})
@@ -79,7 +195,12 @@ defmodule LSG.IRC.PreumsPlugin do
Keyword.get(channel_settings, :tz, default) || default
end
- defp handle_preums(m = %IRC.Message{channel: channel, text: text, sender: sender}, state) do
+ defp handle_preums(%IRC.Message{channel: nil}, state) do
+ state
+ end
+
+ defp handle_preums(m = %IRC.Message{text: text, sender: sender}, state) do
+ channel = {m.network, m.channel}
tz = timezone(channel)
{:ok, now} = DateTime.now(tz, Tzdata.TimeZoneDatabase)
date = {now.year, now.month, now.day}
@@ -89,15 +210,16 @@ defmodule LSG.IRC.PreumsPlugin do
case :dets.lookup(state.dets, key) do
[item = {^key, _nick, _now, _perfect, _text}] ->
# Preums lost, but wasn't cached
- state = Map.put(state, channel, %{date => item})
- state
- _ ->
+ Map.put(state, channel, %{date => item})
+ [] ->
# Preums won!
perfect? = Enum.any?(@perfects, fn(perfect) -> Regex.match?(perfect, text) end)
- item = {key, sender.nick, now, perfect?, text}
+ item = {key, m.account.id, now, perfect?, text}
:dets.insert(state.dets, item)
:dets.sync(state.dets)
- state = Map.put(state, channel, %{date => item})
+ Map.put(state, channel, %{date => item})
+ {:error, _} = error ->
+ Logger.error("#{__MODULE__} dets lookup failed: #{inspect error}")
state
end
else