summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/txt_plugin.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lsg_irc/txt_plugin.ex')
-rw-r--r--lib/lsg_irc/txt_plugin.ex141
1 files changed, 110 insertions, 31 deletions
diff --git a/lib/lsg_irc/txt_plugin.ex b/lib/lsg_irc/txt_plugin.ex
index ca1be9c..f8c3a29 100644
--- a/lib/lsg_irc/txt_plugin.ex
+++ b/lib/lsg_irc/txt_plugin.ex
@@ -3,11 +3,11 @@ defmodule LSG.IRC.TxtPlugin do
require Logger
@moduledoc """
- # [txt](/irc/txt)
+ # [txt]({{context_path}}/txt)
* **.txt**: liste des fichiers et statistiques.
Les fichiers avec une `*` sont vérrouillés.
- [Voir sur le web](/irc/txt).
+ [Voir sur le web]({{context_path}}/txt).
* **!txt**: lis aléatoirement une ligne dans tous les fichiers.
* **!txt `<recherche>`**: recherche une ligne dans tous les fichiers.
@@ -56,7 +56,7 @@ defmodule LSG.IRC.TxtPlugin do
#
def handle_info({:irc, :trigger, "txtrw", msg = %{channel: channel, trigger: %{type: :plus}}}, state = %{rw: false}) do
- if channel && UserTrack.operator?(channel, msg.sender.nick) do
+ if channel && UserTrack.operator?(msg.network, channel, msg.sender.nick) do
msg.replyfun.("txt: écriture réactivée")
{:noreply, %__MODULE__{state | rw: true}}
else
@@ -65,7 +65,7 @@ defmodule LSG.IRC.TxtPlugin do
end
def handle_info({:irc, :trigger, "txtrw", msg = %{channel: channel, trigger: %{type: :minus}}}, state = %{rw: true}) do
- if channel && UserTrack.operator?(channel, msg.sender.nick) do
+ if channel && UserTrack.operator?(msg.network, channel, msg.sender.nick) do
msg.replyfun.("txt: écriture désactivée")
{:noreply, %__MODULE__{state | rw: false}}
else
@@ -80,7 +80,7 @@ defmodule LSG.IRC.TxtPlugin do
def handle_info({:irc, :trigger, "txtlock", msg = %{trigger: %{type: :plus, args: [trigger]}}}, state) do
with \
{trigger, _} <- clean_trigger(trigger),
- true <- UserTrack.operator?(msg.channel, msg.sender.nick)
+ true <- UserTrack.operator?(msg.network, msg.channel, msg.sender.nick)
do
:dets.insert(state.locks, {trigger})
msg.replyfun.("txt: #{trigger} verrouillé")
@@ -91,7 +91,7 @@ defmodule LSG.IRC.TxtPlugin do
def handle_info({:irc, :trigger, "txtlock", msg = %{trigger: %{type: :minus, args: [trigger]}}}, state) do
with \
{trigger, _} <- clean_trigger(trigger),
- true <- UserTrack.operator?(msg.channel, msg.sender.nick),
+ true <- UserTrack.operator?(msg.network, msg.channel, msg.sender.nick),
true <- :dets.member(state.locks, trigger)
do
:dets.delete(state.locks, trigger)
@@ -132,7 +132,6 @@ defmodule LSG.IRC.TxtPlugin do
def handle_info({:irc, :trigger, "txt", msg = %{trigger: %{type: :bang, args: []}}}, state) do
result = Enum.reduce(state.triggers, [], fn({trigger, data}, acc) ->
- IO.puts inspect(data)
Enum.reduce(data, acc, fn({l, _}, acc) ->
[{trigger, l} | acc]
end)
@@ -141,28 +140,92 @@ defmodule LSG.IRC.TxtPlugin do
if !Enum.empty?(result) do
{source, line} = Enum.random(result)
- msg.replyfun.(format_line(line, "#{source}: "))
+ msg.replyfun.(format_line(line, "#{source}: ", msg))
end
{:noreply, state}
end
def handle_info({:irc, :trigger, "txt", msg = %{trigger: %{type: :bang, args: args}}}, state) do
grep = Enum.join(args, " ")
- result = Enum.reduce(state.triggers, [], fn({trigger, data}, acc) ->
- Enum.reduce(data, acc, fn({l, _}, acc) ->
- [{trigger, l} | acc]
+ result = with_stateful_results(msg, {:bang,"txt",grep}, fn() ->
+ Enum.reduce(state.triggers, [], fn({trigger, data}, acc) ->
+ Enum.reduce(data, acc, fn({l, _}, acc) ->
+ [{trigger, l} | acc]
+ end)
end)
+ |> Enum.filter(fn({_, line}) -> String.contains?(String.downcase(line), String.downcase(grep)) end)
+ |> Enum.shuffle()
end)
- |> Enum.filter(fn({_, line}) -> String.contains?(String.downcase(line), String.downcase(grep)) end)
- |> Enum.shuffle()
- if !Enum.empty?(result) do
- {source, line} = Enum.random(result)
+ if result do
+ {source, line} = result
msg.replyfun.(["#{source}: ", line])
end
{:noreply, state}
end
+ def with_stateful_results(msg, key, initfun) do
+ me = self()
+ scope = {msg.network, msg.channel || msg.sender.nick}
+ key = {__MODULE__, me, scope, key}
+ with_stateful_results(key, initfun)
+ end
+
+ def with_stateful_results(key, initfun) do
+ IO.puts("Stateful results key is #{inspect key}")
+ pid = case :global.whereis_name(key) do
+ :undefined ->
+ start_stateful_results(key, initfun.())
+ pid -> pid
+ end
+ if pid, do: wait_stateful_results(key, initfun, pid)
+ end
+
+ def start_stateful_results(key, []) do
+ nil
+ end
+
+ def start_stateful_results(key, list) do
+ me = self()
+ {pid, _} = spawn_monitor(fn() ->
+ Process.monitor(me)
+ stateful_results(me, list)
+ end)
+ :yes = :global.register_name(key, pid)
+ pid
+ end
+
+ def wait_stateful_results(key, initfun, pid) do
+ send(pid, :get)
+ receive do
+ {:stateful_results, line} ->
+ line
+ {:DOWN, _ref, :process, ^pid, reason} ->
+ with_stateful_results(key, initfun)
+ after
+ 5000 ->
+ nil
+ end
+ end
+
+ defp stateful_results(owner, []) do
+ send(owner, :empty)
+ :ok
+ end
+
+ @stateful_results_expire :timer.minutes(30)
+ defp stateful_results(owner, [line | rest] = acc) do
+ receive do
+ :get ->
+ send(owner, {:stateful_results, line})
+ stateful_results(owner, rest)
+ {:DOWN, _ref, :process, ^owner, _} ->
+ :ok
+ after
+ @stateful_results_expire -> :ok
+ end
+ end
+
#
# GLOBAL: MARKOV
#
@@ -209,12 +272,25 @@ defmodule LSG.IRC.TxtPlugin do
# TXT: RANDOM
#
+ def handle_info({:irc, :trigger, trigger, m = %{trigger: %{type: :query, args: opts}}}, state) do
+ {trigger, _} = clean_trigger(trigger)
+ if Map.get(state.triggers, trigger) do
+ url = if m.channel do
+ LSGWeb.Router.Helpers.irc_url(LSGWeb.Endpoint, :txt, m.network, LSGWeb.format_chan(m.channel), trigger)
+ else
+ LSGWeb.Router.Helpers.irc_url(LSGWeb.Endpoint, :txt, trigger)
+ end
+ m.replyfun.("-> #{url}")
+ end
+ {:noreply, state}
+ end
+
def handle_info({:irc, :trigger, trigger, msg = %{trigger: %{type: :bang, args: opts}}}, state) do
{trigger, _} = clean_trigger(trigger)
IO.puts "OPTS : #{inspect {trigger, opts}}"
- line = get_random(state.triggers, trigger, String.trim(Enum.join(opts, " ")))
+ line = get_random(msg, state.triggers, trigger, String.trim(Enum.join(opts, " ")))
if line do
- msg.replyfun.(format_line(line))
+ msg.replyfun.(format_line(line, nil, msg))
end
{:noreply, state}
end
@@ -310,7 +386,7 @@ defmodule LSG.IRC.TxtPlugin do
File.write!(directory() <> "/" <> trigger <> ".txt", data<>"\n", [])
end
- defp get_random(triggers, trigger, []) do
+ defp get_random(msg, triggers, trigger, []) do
if data = Map.get(triggers, trigger) do
{data, _idx} = Enum.random(data)
data
@@ -319,16 +395,16 @@ defmodule LSG.IRC.TxtPlugin do
end
end
- defp get_random(triggers, trigger, opt) do
+ defp get_random(msg, triggers, trigger, opt) do
arg = case Integer.parse(opt) do
{pos, ""} -> {:index, pos}
{_pos, _some_string} -> {:grep, opt}
_error -> {:grep, opt}
end
- get_with_param(triggers, trigger, arg)
+ get_with_param(msg, triggers, trigger, arg)
end
- defp get_with_param(triggers, trigger, {:index, pos}) do
+ defp get_with_param(msg, triggers, trigger, {:index, pos}) do
data = Map.get(triggers, trigger, %{})
case Enum.find(data, fn({_, index}) -> index+1 == pos end) do
{text, _} -> text
@@ -336,14 +412,15 @@ defmodule LSG.IRC.TxtPlugin do
end
end
- defp get_with_param(triggers, trigger, {:grep, query}) do
- data = Map.get(triggers, trigger, %{})
- regex = Regex.compile!("#{query}", "i")
- out = Enum.filter(data, fn({txt, _}) -> Regex.match?(regex, txt) end)
- |> Enum.map(fn({txt, _}) -> txt end)
- if !Enum.empty?(out) do
- Enum.random(out)
- end
+ defp get_with_param(msg, triggers, trigger, {:grep, query}) do
+ out = with_stateful_results(msg, {:grep, trigger, query}, fn() ->
+ data = Map.get(triggers, trigger, %{})
+ regex = Regex.compile!("#{query}", "i")
+ Enum.filter(data, fn({txt, _}) -> Regex.match?(regex, txt) end)
+ |> Enum.map(fn({txt, _}) -> txt end)
+ |> Enum.shuffle()
+ end)
+ if out, do: out
end
defp create_file(name) do
@@ -380,7 +457,8 @@ defmodule LSG.IRC.TxtPlugin do
{trigger, opts}
end
- defp format_line(line, prefix \\ "") do
+ defp format_line(line, prefix, msg) do
+ prefix = unless(prefix, do: "", else: prefix)
prefix <> line
|> String.split("\\\\")
|> Enum.map(fn(line) ->
@@ -389,6 +467,7 @@ defmodule LSG.IRC.TxtPlugin do
|> List.flatten()
|> Enum.map(fn(line) ->
String.trim(line)
+ |> Tmpl.render(msg)
end)
end
@@ -415,7 +494,7 @@ defmodule LSG.IRC.TxtPlugin do
defp can_write?(state = %__MODULE__{rw: rw?, locks: locks}, msg = %{channel: channel, sender: sender}, trigger) do
admin? = IRC.admin?(sender)
- operator? = IRC.UserTrack.operator?(channel, sender.nick)
+ operator? = IRC.UserTrack.operator?(msg.network, channel, sender.nick)
locked? = case :dets.lookup(locks, trigger) do
[{trigger}] -> true
_ -> false