diff options
author | Jordan Bracco <href@random.sh> | 2022-12-20 02:13:47 +0000 |
---|---|---|
committer | Jordan Bracco <href@random.sh> | 2022-12-20 19:29:41 +0100 |
commit | 70b9bba56f5319361ce5a7df5c489b9c0d6905ce (patch) | |
tree | f9b4438965f4c5e3e1f3a6129904cbb9a37047f2 /lib/nola_plugins/preums_plugin.ex | |
parent | Update repo URL, refs T77. (diff) |
Rename to Nola
Summary:
Nola rename cont. pt. 2. Refs T77.
`find lib -name "*.ex" -type f | xargs sed -i '' 's/LSG/Nola/g'`
Nola rename, cont. pt. 3. Refs T77.
`s/:lsg/:nola/g`
Nola rename, cont. pt. 4. Refs T77.
Nola rename, cont. pt. 5. Refs T77. Configs.
find config -type f | xargs sed -i '' 's/LSG/Nola/g'
find config -type f | xargs sed -i '' 's/lsg/nola/g'
BREAKING CHANGE: Config keys switch from `:lsg` to `:nola`
Nola rename, the end. pt 6. Refs T77.
Nola rename: The Big Move, Refs T77
Update repo URL, refs T77.
Nola rename: Nola.Plugins, refs T77
Maniphest Tasks: T77
Differential Revision: https://phab.random.sh/D3
Diffstat (limited to 'lib/nola_plugins/preums_plugin.ex')
-rw-r--r-- | lib/nola_plugins/preums_plugin.ex | 276 |
1 files changed, 0 insertions, 276 deletions
diff --git a/lib/nola_plugins/preums_plugin.ex b/lib/nola_plugins/preums_plugin.ex deleted file mode 100644 index f250e85..0000000 --- a/lib/nola_plugins/preums_plugin.ex +++ /dev/null @@ -1,276 +0,0 @@ -defmodule Nola.IRC.PreumsPlugin do - @moduledoc """ - # preums !!! - - * `!preums`: affiche le preums du jour - * `.preums`: stats des preums - """ - - # WIP Scores - # L'idée c'est de donner un score pour mettre un peu de challenge en pénalisant les preums faciles. - # - # Un preums ne vaut pas 1 point, mais plutôt 0.10 ou 0.05, et on arrondi au plus proche. C'est un jeu sur le long - # terme. Un gros bonus pourrait apporter beaucoup de points. - # - # Il faudrait ces données: - # - moyenne des preums - # - activité récente du channel et par nb actifs d'utilisateurs - # (aggréger memberships+usertrack last_active ?) - # (faire des stats d'activité habituelle (un peu a la pisg) ?) - # - preums consécutifs - # - # Malus: - # - est proche de la moyenne en faible activité - # - trop consécutif de l'utilisateur sauf si activité - # - # Bonus: - # - plus le preums est éloigné de la moyenne - # - après 18h double - # - plus l'activité est élévée, exponentiel selon la moyenne - # - derns entre 4 et 6 (pourrait être adapté selon les stats d'activité) - # - # WIP Badges: - # - derns - # - streaks - # - faciles - # - ? - - 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}, 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 - - fun = fn(x = {{chan, date}, account_id, time, perfect, text}, acc) -> - if (channel == nil and chan) or (channel == chan) do - {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}) - else - acc - end - end - :dets.foldl(fun, %{}, dets) - |> 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 - - def dets do - (Nola.data_path() <> "/preums.dets") |> String.to_charlist() - end - - def init([]) do - regopts = [plugin: __MODULE__] - {:ok, _} = Registry.register(IRC.PubSub, "account", regopts) - {:ok, _} = Registry.register(IRC.PubSub, "messages", regopts) - {:ok, _} = Registry.register(IRC.PubSub, "triggers", regopts) - {: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{trigger: %IRC.Trigger{type: :bang}}}, state) do - channelkey = {m.network, m.channel} - state = handle_preums(m, state) - tz = timezone(channelkey) - {:ok, now} = DateTime.now(tz, Tzdata.TimeZoneDatabase) - 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 - end - end - - if item do - {_, account_id, date, _perfect, text} = item - h = "#{date.hour}:#{date.minute}:#{date.second}" - account = IRC.Account.get(account_id) - user = IRC.UserTrack.find_by_account(m.network, account) - 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 = %IRC.Message{trigger: %IRC.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 = IRC.Account.get(account_id) - user = IRC.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 = %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 - - # Trigger fallback - def handle_info({:irc, :trigger, _, m = %IRC.Message{}}, state) do - state = handle_preums(m, state) - {:noreply, state} - end - - # Message fallback - def handle_info({:irc, :text, m = %IRC.Message{}}, state) 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(:nola, Nola.IRC.PreumsPlugin, []) - channels = Keyword.get(env, :channels, %{}) - channel_settings = Map.get(channels, channel, []) - default = Keyword.get(env, :default_tz, "Europe/Paris") - Keyword.get(channel_settings, :tz, default) || default - end - - 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} - 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) - 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}") - state - end - else - state - end - end - - def score(_chan, _account, _time, _perfect, _text) do - 1 - end - - -end |