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/irc | |
parent | link_plugin: improve twitter, youtube & logging (diff) |
irc_plugin util: tempref
Diffstat (limited to 'lib/irc')
-rw-r--r-- | lib/irc/plugin/temp_ref.ex | 95 |
1 files changed, 95 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 |