Skip to content

Commit

Permalink
feat(dummy): easy direct messaging method
Browse files Browse the repository at this point in the history
  • Loading branch information
ProducerMatt committed Aug 30, 2024
1 parent 77830f0 commit e474e1e
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 61 deletions.
93 changes: 46 additions & 47 deletions .dialyzer_ignore.exs
Original file line number Diff line number Diff line change
@@ -1,49 +1,48 @@
[
{"deps/type_check/lib/type_check/spec.ex",
"The pattern can never match the type {:ok, [], _}."},
{"lib/plugin.ex", "Function usage_tuples/0 has no local return."},
{"lib/plugin.ex", "Function job_result/0 has no local return."},
{"lib/plugin.ex", "Function plugin_job_result/0 has no local return."},
{"lib/plugin.ex", "The guard clause can never succeed."},
{"lib/services/discord.ex", "Function vips/0 has no local return."},
{"lib/services/dummy.ex", "Function dummy_channel_id/0 has no local return."},
{"lib/services/dummy.ex", "Function msg_reference/0 has no local return."},
{"lib/services/dummy.ex", "Function incoming_msg_tuple/0 has no local return."},
{"lib/services/dummy.ex", "Function retrieved_msg_tuple/0 has no local return."},
{"lib/services/dummy.ex", "Function channel_log/0 has no local return."},
{"lib/services/dummy.ex", "Function server_log/0 has no local return."},
{"lib/services/dummy/channel.ex", "Function t/0 has no local return."},
{"lib/site_config.ex", "Function server_id/0 has no local return."},
{"lib/site_config.ex", "Function schema/0 has no local return."},
{"lib/site_config.ex", "Function cfg_list/0 has no local return."},
{"lib/stampede.ex", "Function dm_tuple/0 has no local return."},
{"lib/stampede.ex", "Function server_id/0 has no local return."},
{"lib/stampede.ex", "Function prefix/0 has no local return."},
{"lib/stampede.ex", "Function enabled_plugs/0 has no local return."},
{"lib/stampede.ex", "Function channel_lock_action/0 has no local return."},
{"lib/stampede.ex", "Function channel_lock_status/0 has no local return."},
{"lib/stampede.ex", "Function timestamp/0 has no local return."},
{"lib/stampede.ex", "Function bot_invoked_status/0 has no local return."},
{"lib/stampede.ex", "Function module_function_args/0 has no local return."},
{"lib/stampede.ex", "Function log_level/0 has no local return."},
{"lib/stampede.ex", "Function log_msg/0 has no local return."},
{"lib/stampede.ex", "Function kwlist/1 has no local return."},
{"lib/stampede.ex", "Function kwlist/0 has no local return."},
{"lib/stampede.ex", "Function str_list/0 has no local return."},
{"lib/stampede.ex", "Function throw_internal_error/0 has no local return."},
{"lib/stampede.ex", "Function throw_internal_error/1 only terminates with explicit exception."},
{"lib/stampede/cfg_table.ex", "Function vips/0 has no local return."},
{"lib/stampede/cfg_table.ex", "Function table_object/0 has no local return."},
{"lib/stampede/external/python.ex", "The pattern can never match the type true."},
{"lib/stampede/external/python.ex",
"Function do_dumb_down_elixir_term/1 will never be called."},
{"lib/stampede/logger.ex", "Function logger_state/0 has no local return."},
{"lib/stampede/tables/channel_locks.ex", "The guard clause can never succeed."},
{"lib/stampede/tables/dummy_msgs.ex", "The guard clause can never succeed."},
{"lib/stampede/tables/interactions.ex", "The guard clause can never succeed."},
{"lib/stampede/traceback.ex", "Function t/0 has no local return."},
{"lib/txt_block.ex", "Function block/0 has no local return."},
{"lib/txt_block.ex", "Function type/0 has no local return."},
{"lib/txt_block.ex", "Function t/0 has no local return."},
{"lib/txt_block/md.ex", "The guard clause can never succeed."}
{"deps/type_check/lib/type_check/spec.ex", "The pattern can never match the type {:ok, [], _}."},
{"lib/plugin.ex", "Function usage_tuples/0 has no local return."},
{"lib/plugin.ex", "Function job_result/0 has no local return."},
{"lib/plugin.ex", "Function plugin_job_result/0 has no local return."},
{"lib/plugin.ex", "The guard clause can never succeed."},
{"lib/services/discord.ex", "Function vips/0 has no local return."},
{"lib/services/dummy.ex", "Function dummy_channel_id/0 has no local return."},
{"lib/services/dummy.ex", "Function dummy_server_id/0 has no local return."},
{"lib/services/dummy.ex", "Function msg_reference/0 has no local return."},
{"lib/services/dummy.ex", "Function incoming_msg_tuple/0 has no local return."},
{"lib/services/dummy.ex", "Function retrieved_msg_tuple/0 has no local return."},
{"lib/services/dummy.ex", "Function channel_log/0 has no local return."},
{"lib/services/dummy.ex", "Function server_log/0 has no local return."},
{"lib/services/dummy/channel.ex", "Function t/0 has no local return."},
{"lib/site_config.ex", "Function server_id/0 has no local return."},
{"lib/site_config.ex", "Function schema/0 has no local return."},
{"lib/site_config.ex", "Function cfg_list/0 has no local return."},
{"lib/stampede.ex", "Function dm_tuple/0 has no local return."},
{"lib/stampede.ex", "Function server_id/0 has no local return."},
{"lib/stampede.ex", "Function prefix/0 has no local return."},
{"lib/stampede.ex", "Function enabled_plugs/0 has no local return."},
{"lib/stampede.ex", "Function channel_lock_action/0 has no local return."},
{"lib/stampede.ex", "Function channel_lock_status/0 has no local return."},
{"lib/stampede.ex", "Function timestamp/0 has no local return."},
{"lib/stampede.ex", "Function bot_invoked_status/0 has no local return."},
{"lib/stampede.ex", "Function module_function_args/0 has no local return."},
{"lib/stampede.ex", "Function log_level/0 has no local return."},
{"lib/stampede.ex", "Function log_msg/0 has no local return."},
{"lib/stampede.ex", "Function kwlist/1 has no local return."},
{"lib/stampede.ex", "Function kwlist/0 has no local return."},
{"lib/stampede.ex", "Function str_list/0 has no local return."},
{"lib/stampede.ex", "Function throw_internal_error/0 has no local return."},
{"lib/stampede.ex", "Function throw_internal_error/1 only terminates with explicit exception."},
{"lib/stampede/cfg_table.ex", "Function vips/0 has no local return."},
{"lib/stampede/cfg_table.ex", "Function table_object/0 has no local return."},
{"lib/stampede/external/python.ex", "The pattern can never match the type true."},
{"lib/stampede/external/python.ex", "Function do_dumb_down_elixir_term/1 will never be called."},
{"lib/stampede/logger.ex", "Function logger_state/0 has no local return."},
{"lib/stampede/tables/channel_locks.ex", "The guard clause can never succeed."},
{"lib/stampede/tables/dummy_msgs.ex", "The guard clause can never succeed."},
{"lib/stampede/tables/interactions.ex", "The guard clause can never succeed."},
{"lib/stampede/traceback.ex", "Function t/0 has no local return."},
{"lib/txt_block.ex", "Function block/0 has no local return."},
{"lib/txt_block.ex", "Function type/0 has no local return."},
{"lib/txt_block.ex", "Function t/0 has no local return."},
{"lib/txt_block/md.ex", "The guard clause can never succeed."},
]
53 changes: 48 additions & 5 deletions lib/services/dummy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule Services.Dummy do
# Imaginary server types
@type! dummy_user_id :: atom()
@type! dummy_channel_id :: atom() | nil
@type! dummy_server_id :: identifier() | atom()
@type! dummy_server_id :: identifier() | atom() | {:dm, __MODULE__}
@type! dummy_msg_id :: integer()
# "one channel"
@type! msg_content :: String.t()
Expand Down Expand Up @@ -45,7 +45,7 @@ defmodule Services.Dummy do
],
server_id: [
required: true,
type: :atom
type: {:or, [:atom, {:in, ["DM", {:dm, __MODULE__}]}]}
],
error_channel_id: [
default: :error,
Expand Down Expand Up @@ -162,10 +162,39 @@ defmodule Services.Dummy do
end
end

def default_server(),
do: {:dm, __MODULE__}

def default_channel(),
do: :default_channel

def ask_bot(unformatted_text) do
default_config = [
server_id: "DM",
prefix: "!",
plugs: :all,
dm_handler: true,
bot_is_loud: true
]

# Register default server if it isn't already
_ =
case Stampede.CfgTable.get_cfg(__MODULE__, default_server()) do
{:error, :server_notfound} ->
default_config
|> new_server()

{:ok, _} ->
:ok
end

ask_bot(default_server(), default_channel(), @system_user, unformatted_text)
end

def new_server(cfg_kwlist) when is_list(cfg_kwlist) do
cfg_kwlist
|> Keyword.put(:service, :dummy)
|> SiteConfig.validate!(site_config_schema())
|> SiteConfig.validate!(site_config_schema(), [&hack_dummy_dm_handler/2])
|> S.CfgTable.insert_cfg()

# Just to be safe
Expand Down Expand Up @@ -256,10 +285,11 @@ defmodule Services.Dummy do
end

@impl Service
def dm?({_id, _server_id = {:dm, __MODULE__}, _channel, _user, _body, _ref}),
@spec! dm?(MsgReceived.t()) :: boolean()
def dm?(%MsgReceived{server_id: {:dm, __MODULE__}}),
do: true

def dm?(_other), do: false
def dm?(%MsgReceived{}), do: false

@impl Service
def author_privileged?(server_id, author_id) do
Expand Down Expand Up @@ -335,6 +365,19 @@ defmodule Services.Dummy do
end)
end

# Transform function for use in `SiteConfig.validate!/3`. This is a hack because it's dodging the duplicate checking done in `SiteConfig.make_configs_for_dm_handling/1`.
defp hack_dummy_dm_handler(kwlist, _schema) do
case kwlist[:server_id] do
"DM" ->
kwlist
|> Keyword.put(:server_id, S.make_dm_tuple(Services.Dummy))
|> Keyword.put(:dm_handler, true)

_ ->
kwlist
end
end

@impl Supervisor
def init(_ \\ []) do
children = [
Expand Down
5 changes: 3 additions & 2 deletions lib/site_config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -255,16 +255,17 @@ defmodule SiteConfig do
@doc """
Create a config with key {:dm, service} which all DMs for a service will be handled under.
If server_id is not "DM", it will be duplicated with one for the server and
one for the DMs.
one for the DMs. This lets you use the same settings for a server and for DMs, when convenient.
Collects all VIPs for that service and puts them in the DM config.
"""
# TODO: make this happen across entire cfg table on every new config load. Maybe have a dedicated sanity-checking stage that can refuse bad configs.
def make_configs_for_dm_handling(service_map) do
Map.new(service_map, fn {service, site_map} ->
dupe_checked =
Enum.reduce(
site_map,
{Map.new(), MapSet.new(), MapSet.new()},
# Accumulator keeps a map for the sites being processed, and a mapset to check for duplicate keys
# Accumulator keeps a map for the sites being processed, and two mapsets to check for duplicate keys
fn {server_id, orig_cfg}, {site_acc, services_handled, service_vips} ->
if not orig_cfg.dm_handler do
{
Expand Down
12 changes: 7 additions & 5 deletions lib/stampede/tables/dummy_msgs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,18 @@ defmodule Stampede.Tables.DummyMsgs do
|> validate!()
end

alias Services.Dummy, as: D

def validate!(record) when is_struct(record, __MODULE__) do
if S.enable_typechecking?() do
record
|> TypeCheck.conforms!(%__MODULE__{
id: non_neg_integer(),
id: D.dummy_msg_id(),
datetime: S.timestamp(),
server_id: atom(),
channel: atom(),
user: atom(),
body: any(),
server_id: D.dummy_server_id(),
channel: D.dummy_channel_id(),
user: D.dummy_user_id(),
body: binary(),
referenced_msg_id: nil | integer()
})
else
Expand Down
2 changes: 0 additions & 2 deletions test/stampede_stateless_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@ defmodule StampedeStatelessTest do
%{cfg.service => %{cfg.server_id => cfg}}
|> SiteConfig.make_configs_for_dm_handling()

# |> IO.inspect(pretty: true) # Debug

key = S.make_dm_tuple(cfg.service)

assert key ==
Expand Down
4 changes: 4 additions & 0 deletions test/stampede_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ defmodule StampedeTest do

assert r.text == "pong!"
end

test "Direct messaging with D.ask_bot/1" do
assert_value Map.fetch!(D.ask_bot("ping"), :text) == "pong!"
end
end

describe "dummy server channels" do
Expand Down

0 comments on commit e474e1e

Please sign in to comment.