Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find and store ID of the message that an interaction caused #10

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .dialyzer_ignore.exs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
[
{"deps/nostrum/lib/nostrum/consumer.ex", "Function Nostrum.ConsumerGroup.join/1 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Api.get_channel_message/2 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Cache.Me.get/0 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Api.create_message/2 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Api.get_user!/1 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Struct.User.full_name/1 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Api.get_channel_message/2 does not exist."},
{"lib/service/discord.ex", "Function Nostrum.Cache.Me.get/0 does not exist."},
{"lib/stampede/application.ex", "Function Mix.env/0 does not exist."},
{"lib/stampede/interact.ex", "Function Mix.env/0 does not exist."},
{"/build/source/lib/elixir/lib/gen_server.ex", "Callback info about the Nostrum.Consumer behaviour is not available."},
{"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/service/discord.ex", "Function vips/0 has no local return."},
{"lib/service/discord.ex", "Function logger_state/0 has no local return."},
{"lib/service/dummy.ex", "@spec for send_msg has more types than are returned by the function."},
{"lib/service/dummy.ex", "Function dummy_channel_id/0 has no local return."},
Expand All @@ -21,7 +22,10 @@
{"lib/service/dummy.ex", "Function msg_tuple_incoming/0 has no local return."},
{"lib/service/dummy.ex", "Function channel/0 has no local return."},
{"lib/service/dummy.ex", "Function channel_buffers/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 server_id/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 prefix/0 has no local return."},
Expand All @@ -33,7 +37,10 @@
{"lib/stampede.ex", "Function channel_lock_status/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/interact.ex", "Function mod_state/0 has no local return."},
{"lib/stampede/table_ids.ex", "Function mod_state/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."},
Expand Down
83 changes: 47 additions & 36 deletions lib/plugin.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ defmodule Plugin do
require PluginCrashInfo
alias PluginCrashInfo, as: CrashInfo
alias Stampede, as: S
alias S.{Msg, Response, Interaction}
require Interaction
alias S.{Msg, Response, InteractionForm}
require InteractionForm
@first_response_timeout 500

@typedoc """
Expand Down Expand Up @@ -150,6 +150,8 @@ defmodule Plugin do
end
end

@spec! query_plugins(list(S.module_function_args() | module()), SiteConfig.t(), S.Msg.t()) ::
nil | {response :: Response.t(), interaction_id :: S.interaction_id()}
def query_plugins(call_list, cfg, msg) do
tasks =
Enum.map(call_list, fn
Expand Down Expand Up @@ -229,17 +231,19 @@ defmodule Plugin do
nil ->
nil

chosen_response = %Response{callback: nil} ->
S.Interaction.new(
plugin: chosen_response.origin_plug,
msg: msg,
response: chosen_response,
channel_lock: chosen_response.channel_lock,
traceback: traceback
)
|> S.Interact.record_interaction!()
%Response{callback: nil} ->
{:ok, iid} =
S.InteractionForm.new(
service: cfg.service,
plugin: chosen_response.origin_plug,
msg: msg,
response: chosen_response,
channel_lock: chosen_response.channel_lock,
traceback: traceback
)
|> S.Interact.prepare_interaction!()

chosen_response
{chosen_response, iid}

%Response{callback: {mod, fun, args}} ->
followup =
Expand All @@ -253,41 +257,48 @@ defmodule Plugin do
followup.why
]

S.Interaction.new(
plugin: chosen_response.origin_plug,
msg: msg,
response: followup,
channel_lock: followup.channel_lock,
traceback: new_tb
)
|> S.Interact.record_interaction!()
{:ok, iid} =
S.InteractionForm.new(
service: cfg.service,
plugin: chosen_response.origin_plug,
msg: msg,
response: followup,
channel_lock: followup.channel_lock,
traceback: new_tb
)
|> S.Interact.prepare_interaction!()

followup
{followup, iid}
end
end

@doc "Poll all enabled plugins and choose the most relevant one."
@spec! get_top_response(SiteConfig.t(), Msg.t()) :: nil | Response.t()
@spec! get_top_response(SiteConfig.t(), Msg.t()) ::
nil | {response :: Response.t(), interaction_id :: S.interaction_id()}
def get_top_response(cfg, msg) do
case S.Interact.channel_locked?(msg.channel_id) do
{{m, f, a}, _plugin, _iid} ->
response = query_plugins([{m, f, [cfg, msg | a]}], cfg, msg)

Map.update!(response, :why, fn tb ->
[
"Channel ",
msg.channel_id |> inspect(),
"was locked to module ",
m |> inspect(),
", function ",
"f",
", so we called it.\n"
| tb
]
end)
{response, iid} = query_plugins([{m, f, [cfg, msg | a]}], cfg, msg)

explained_response =
Map.update!(response, :why, fn tb ->
[
"Channel ",
msg.channel_id |> inspect(),
"was locked to module ",
m |> inspect(),
", function ",
"f",
", so we called it.\n"
| tb
]
end)

{explained_response, iid}

false ->
__MODULE__.ls(SiteConfig.fetch!(cfg, :plugs))
|> MapSet.to_list()
|> query_plugins(cfg, msg)
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/plugin/why.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ defmodule Plugin.Why do
require Stampede.Response
alias Plugin.Why.Debugging
alias Stampede, as: S
alias S.{Response, Interaction}
require Interaction
alias S.{Response, InteractionForm}
require InteractionForm

use Plugin

Expand Down
15 changes: 11 additions & 4 deletions lib/service/discord.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ defmodule Service.Discord do
@consecutive_msg_limit 10

@impl Service
@spec! into_msg(service_msg :: %Nostrum.Struct.Message{}) :: S.Msg.t()
def into_msg(msg) do
Msg.new(
id: msg.id,
Expand Down Expand Up @@ -154,6 +155,7 @@ defmodule Service.Discord do
send_msg(
channel_id,
formatted
|> TxtBlock.to_str_list(Service.Discord)
)
end)

Expand Down Expand Up @@ -323,11 +325,11 @@ defmodule Service.Discord.Handler do
else
cond do
discord_msg.guild_id in state.guild_ids ->
do_msg_create(discord_msg)
:ok = do_msg_create(discord_msg)

Discord.dm?(discord_msg) ->
if vip_in_this_context?(state.vip_ids, discord_msg.guild_id, discord_msg.author.id) do
do_msg_create(discord_msg)
:ok = do_msg_create(discord_msg)
else
Logger.warning(fn ->
[
Expand Down Expand Up @@ -363,12 +365,17 @@ defmodule Service.Discord.Handler do
our_cfg = S.CfgTable.get_cfg!(Discord, our_msg.server_id)

case Plugin.get_top_response(our_cfg, our_msg) do
%Response{text: r_text} when r_text != nil ->
Api.create_message(our_msg.channel_id, r_text)
{%Response{text: r_text}, iid} when r_text != nil ->
{:ok, %{id: bot_response_msg_id}} =
Api.create_message(our_msg.channel_id, r_text)

S.Interact.finalize_interaction(iid, bot_response_msg_id)

nil ->
:do_nothing
end

:ok
end
end

Expand Down
36 changes: 24 additions & 12 deletions lib/service/dummy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,13 @@ defmodule Service.Dummy do
msg_content(),
keyword()
) ::
%{response: nil | Response.t(), posted_msg_id: dummy_msg_id()} | nil | Response.t()
%{
response: nil | Response.t(),
posted_msg_id: dummy_msg_id(),
bot_response_msg_id: nil | dummy_msg_id()
}
| nil
| Response.t()
def send_msg(server_id, channel, user, text, opts \\ []) do
GenServer.call(__MODULE__, {:add_msg, {server_id, channel, user, text, opts[:ref]}, opts})
end
Expand Down Expand Up @@ -310,21 +316,27 @@ defmodule Service.Dummy do
{:reply, nil, state}
else
%{
msg_id: incoming_msg_id,
msg_object: incoming_msg,
posted_msg_id: incoming_msg_id,
posted_msg_object: incoming_msg,
new_state: new_state_1
} = do_add_new_msg(msg_tuple, state)

cfg = S.CfgTable.get_cfg!(__MODULE__, server_id)
response = Plugin.get_top_response(cfg, incoming_msg)

result =
case response do
response when is_struct(response, Response) ->
%{new_state: new_state_2} =
case Plugin.get_top_response(cfg, incoming_msg) do
{response, iid} when is_struct(response, Response) ->
%{new_state: new_state_2, posted_msg_id: bot_response_msg_id} =
do_post_response({server_id, channel}, response, new_state_1)

{:reply, %{response: response, posted_msg_id: incoming_msg_id}, new_state_2}
S.Interact.finalize_interaction(iid, bot_response_msg_id)

{:reply,
%{
response: response,
posted_msg_id: incoming_msg_id,
bot_response_msg_id: bot_response_msg_id
}, new_state_2}

nil ->
{:reply, %{response: nil, posted_msg_id: incoming_msg_id}, new_state_1}
Expand Down Expand Up @@ -391,8 +403,8 @@ defmodule Service.Dummy do
end

@spec! do_add_new_msg(tuple(), %__MODULE__{}) :: %{
msg_id: dummy_msg_id(),
msg_object: %Msg{},
posted_msg_id: dummy_msg_id(),
posted_msg_object: %Msg{},
new_state: %__MODULE__{}
}
defp do_add_new_msg(msg_tuple = {server_id, channel, user, text, ref}, state) do
Expand All @@ -414,8 +426,8 @@ defmodule Service.Dummy do
msg_object = into_msg(msg_tuple |> Tuple.insert_at(0, msg_id))

%{
msg_id: msg_id,
msg_object: msg_object,
posted_msg_id: msg_id,
posted_msg_object: msg_object,
new_state: state
}
end
Expand Down
1 change: 1 addition & 0 deletions lib/stampede.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ defmodule Stampede do
false | {module_function_args(), atom(), integer()}
@type! timestamp :: String.t()
@type! service_name :: atom()
@type! interaction_id :: non_neg_integer()

def confused_response(),
do: "*confused beeping*"
Expand Down
1 change: 1 addition & 0 deletions lib/stampede/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ defmodule Stampede.Application do
default_children = [
{PartitionSupervisor, child_spec: Task.Supervisor, name: Stampede.QuickTaskSupers},
# NOTE: call with Stampede.quick_task_via()
Stampede.TableIds,
{Stampede.CfgTable, config_dir: Keyword.fetch!(startup_args, :config_dir)},
{Stampede.Interact, wipe_tables: Keyword.fetch!(startup_args, :clear_state)}
]
Expand Down
Loading
Loading