summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorhref <href@random.sh>2022-12-11 00:26:34 +0000
committerJordan Bracco <href@random.sh>2022-12-11 02:03:36 +0000
commit325609665474ad0fa64298c9ccc97d85343925b6 (patch)
treeaf32c9afc0a9ff5e6e7a2bcac0f4e05e3f64a387 /lib
parentlink_plugin: improve twitter, youtube & logging (diff)
irc_plugin util: tempref
Diffstat (limited to '')
-rw-r--r--lib/irc/plugin/temp_ref.ex95
-rw-r--r--lib/lsg_irc/logger_plugin.ex60
2 files changed, 155 insertions, 0 deletions
diff --git a/lib/irc/plugin/temp_ref.ex b/lib/irc/plugin/temp_ref.ex
new file mode 100644
index 0000000..84b41bb
--- /dev/null
+++ b/lib/irc/plugin/temp_ref.ex
@@ -0,0 +1,95 @@
+defmodule Irc.Plugin.TempRef do
+ @moduledoc """
+ This module allows to easily implement local temporary simple references for easy access from IRC.
+
+ For example, your plugin output could be acted on, and instead of giving the burden for the user to
+ write or copy that uuid, you could give them a small alphanumeric reference to use instead.
+
+ You can configure how many and for how long the references are kept.
+
+ ## Usage
+
+ `import Irc.Plugin.TempRef`
+
+ ```elixir
+ defmodule Irc.MyPlugin do
+ defstruct [:temprefs]
+
+ def init(_) do
+ # …
+ {:ok, %__MODULE__{temprefs: new_temp_refs()}
+ end
+ end
+ ```
+ """
+
+ defstruct [:refs, :max, :expire, :build_fun, :build_increase_fun, :build_options]
+
+ defmodule SimpleAlphaNumericBuilder do
+ def build(options) do
+ length = Keyword.get(options, :length, 3)
+ for _ <- 1..length, into: "", do: <<Enum.random('bcdfghjkmpqtrvwxy2346789')>>
+ end
+
+ def increase(options) do
+ Keyword.put(options, :length, Keyword.get(options, :length, 3) + 1)
+ end
+ end
+
+ def new_temp_refs(options \\ []) do
+ %__MODULE__{
+ refs: Keyword.get(options, :init_refs, []),
+ max: Keyword.get(options, :max, []),
+ expire: Keyword.get(options, :expire, :infinity),
+ build_fun: Keyword.get(options, :build_fun, &__MODULE__.SimpleAlphaNumericBuilder.build/1),
+ build_increase_fun: Keyword.get(options, :build_increase_fun, &__MODULE__.SimpleAlphaNumericBuilder.increase/1),
+ build_options: Keyword.get(options, :build_options, [length: 3])
+ }
+ end
+
+ def janitor_refs(state = %__MODULE__{}) do
+ if length(state.refs) > state.max do
+ %__MODULE__{refs: state.refs |> Enum.reverse() |> tl() |> Enum.reverse()}
+ else
+ state
+ end
+ end
+
+ def put_temp_ref(data, state = %__MODULE__{}) do
+ state = janitor_refs(state)
+ key = new_nonexisting_key(state)
+ if key do
+ ref = {key, DateTime.utc_now(), data}
+ {key, %__MODULE__{state | refs: [ref | state.refs]}}
+ else
+ {nil, state}
+ end
+ end
+
+ def lookup_temp_ref(key, state, default \\ nil) do
+ case List.keyfind(state.refs, key, 0) do
+ {_, _, data} -> data
+ _ -> nil
+ end
+ end
+
+ defp new_nonexisting_key(state, i) when i > 50 do
+ nil
+ end
+
+ defp new_nonexisting_key(state = %__MODULE__{refs: refs}, i \\ 1) do
+ build_options = if rem(i, 5) == 0 do
+ state.build_increase_fun.(state.build_options)
+ else
+ state.build_options
+ end
+
+ key = state.build_fun.(state.build_options)
+ if !List.keymember?(refs, key, 0) do
+ key
+ else
+ new_nonexisting_key(state, i + 1)
+ end
+ end
+
+end
diff --git a/lib/lsg_irc/logger_plugin.ex b/lib/lsg_irc/logger_plugin.ex
new file mode 100644
index 0000000..667f714
--- /dev/null
+++ b/lib/lsg_irc/logger_plugin.ex
@@ -0,0 +1,60 @@
+defmodule LSG.IRC.LoggerPlugin do
+ require Logger
+
+ @couch_db "bot-logs"
+
+ def irc_doc(), do: nil
+
+ def start_link() do
+ GenServer.start_link(__MODULE__, [], name: __MODULE__)
+ end
+
+ def init([]) do
+ regopts = [plugin: __MODULE__]
+ {:ok, _} = Registry.register(IRC.PubSub, "triggers", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "messages", regopts)
+ {:ok, nil}
+ end
+
+ def handle_info({:irc, :trigger, _, m}, state) do
+ {:noreply, log(m, state)}
+ end
+
+ def handle_info({:irc, :text, m}, state) do
+ {:noreply, log(m, state)}
+ end
+
+ def handle_info(info, state) do
+ Logger.debug("logger_plugin: unhandled info: #{info}")
+ {:noreply, state}
+ end
+
+ def log(entry, state) do
+ case Couch.post(@couch_db, format_to_db(entry)) do
+ {:ok, id, _rev} ->
+ Logger.debug("logger_plugin: saved: #{inspect id}")
+ state
+ error ->
+ Logger.error("logger_plugin: save failed: #{inspect error}")
+ end
+ rescue
+ e ->
+ Logger.error("logger_plugin: rescued processing for #{inspect entry}: #{inspect e}")
+ Logger.error(Exception.format(:error, e, __STACKTRACE__))
+ state
+ catch
+ e, b ->
+ Logger.error("logger_plugin: catched processing for #{inspect entry}: #{inspect e}")
+ Logger.error(Exception.format(e, b, __STACKTRACE__))
+ state
+ end
+
+ def format_to_db(m = %IRC.Message{}) do
+ %IRC.Message{m | replyfun: nil}
+ end
+
+ def format_to_db(anything) do
+ anything
+ end
+
+end