diff options
author | href <href@random.sh> | 2022-12-11 00:26:34 +0000 |
---|---|---|
committer | Jordan Bracco <href@random.sh> | 2022-12-11 02:03:36 +0000 |
commit | 325609665474ad0fa64298c9ccc97d85343925b6 (patch) | |
tree | af32c9afc0a9ff5e6e7a2bcac0f4e05e3f64a387 /lib | |
parent | link_plugin: improve twitter, youtube & logging (diff) |
irc_plugin util: tempref
Diffstat (limited to '')
-rw-r--r-- | lib/irc/plugin/temp_ref.ex | 95 | ||||
-rw-r--r-- | lib/lsg_irc/logger_plugin.ex | 60 |
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 |