mirror of
https://github.com/wanderer-industries/wanderer
synced 2026-05-02 07:20:31 +00:00
159 lines
4.9 KiB
Elixir
159 lines
4.9 KiB
Elixir
defmodule WandererApp.Map.Server.PingsImpl do
|
|
@moduledoc false
|
|
|
|
require Logger
|
|
|
|
alias WandererApp.Map.Server.Impl
|
|
|
|
# @ping_auto_expire_timeout :timer.minutes(15) # reserved for future use
|
|
|
|
def add_ping(
|
|
map_id,
|
|
%{
|
|
solar_system_id: solar_system_id,
|
|
type: type,
|
|
message: message,
|
|
character_id: character_id,
|
|
user_id: user_id
|
|
} = _ping_info
|
|
) do
|
|
with {:ok, character} <- WandererApp.Character.get_character(character_id),
|
|
system <-
|
|
WandererApp.Map.find_system_by_location(map_id, %{
|
|
solar_system_id: solar_system_id |> String.to_integer()
|
|
}),
|
|
{:ok, ping} <-
|
|
WandererApp.MapPingsRepo.create(%{
|
|
map_id: map_id,
|
|
character_id: character_id,
|
|
system_id: system.id,
|
|
message: message,
|
|
type: type
|
|
}) do
|
|
Impl.broadcast!(
|
|
map_id,
|
|
:ping_added,
|
|
ping |> Map.merge(%{character_eve_id: character.eve_id, solar_system_id: solar_system_id})
|
|
)
|
|
|
|
# Broadcast rally point events to external clients (webhooks/SSE)
|
|
if type == 1 do
|
|
WandererApp.ExternalEvents.broadcast(map_id, :rally_point_added, %{
|
|
rally_point_id: ping.id,
|
|
solar_system_id: solar_system_id,
|
|
system_id: system.id,
|
|
character_id: character_id,
|
|
character_name: character.name,
|
|
character_eve_id: character.eve_id,
|
|
system_name: system.name,
|
|
message: message,
|
|
created_at: ping.inserted_at
|
|
})
|
|
end
|
|
|
|
WandererApp.User.ActivityTracker.track_map_event(:map_rally_added, %{
|
|
character_id: character_id,
|
|
user_id: user_id,
|
|
map_id: map_id,
|
|
solar_system_id: "#{solar_system_id}"
|
|
})
|
|
else
|
|
error ->
|
|
Logger.error("Failed to add_ping: #{inspect(error, pretty: true)}")
|
|
end
|
|
end
|
|
|
|
def cancel_ping(
|
|
map_id,
|
|
%{
|
|
id: ping_id,
|
|
character_id: character_id,
|
|
user_id: user_id,
|
|
type: type
|
|
} = _ping_info
|
|
) do
|
|
|
|
result = WandererApp.MapPingsRepo.get_by_id(ping_id)
|
|
|
|
case result do
|
|
{:ok,
|
|
%{system: %{id: system_id, name: system_name, solar_system_id: solar_system_id}} = ping} ->
|
|
with {:ok, character} <- WandererApp.Character.get_character(character_id),
|
|
:ok <- WandererApp.MapPingsRepo.destroy(ping) do
|
|
Logger.debug("Ping #{ping_id} destroyed successfully, broadcasting :ping_cancelled")
|
|
|
|
Impl.broadcast!(map_id, :ping_cancelled, %{
|
|
id: ping_id,
|
|
solar_system_id: solar_system_id,
|
|
type: type
|
|
})
|
|
|
|
Logger.debug("Broadcast :ping_cancelled sent for ping #{ping_id}")
|
|
|
|
# Broadcast rally point removal events to external clients (webhooks/SSE)
|
|
if type == 1 do
|
|
WandererApp.ExternalEvents.broadcast(map_id, :rally_point_removed, %{
|
|
id: ping_id,
|
|
solar_system_id: solar_system_id,
|
|
system_id: system_id,
|
|
character_id: character_id,
|
|
character_name: character.name,
|
|
character_eve_id: character.eve_id,
|
|
system_name: system_name
|
|
})
|
|
end
|
|
|
|
WandererApp.User.ActivityTracker.track_map_event(:map_rally_cancelled, %{
|
|
character_id: character_id,
|
|
user_id: user_id,
|
|
map_id: map_id,
|
|
solar_system_id: solar_system_id
|
|
})
|
|
else
|
|
error ->
|
|
Logger.error("Failed to destroy ping: #{inspect(error, pretty: true)}")
|
|
end
|
|
|
|
# Handle case where ping exists but system was deleted (nil)
|
|
{:ok, %{system: nil} = ping} ->
|
|
case WandererApp.MapPingsRepo.destroy(ping) do
|
|
:ok ->
|
|
Impl.broadcast!(map_id, :ping_cancelled, %{
|
|
id: ping_id,
|
|
solar_system_id: nil,
|
|
type: type
|
|
})
|
|
|
|
error ->
|
|
Logger.error("Failed to destroy orphaned ping: #{inspect(error, pretty: true)}")
|
|
end
|
|
|
|
{:error, %Ash.Error.Query.NotFound{}} ->
|
|
# Ping already deleted (possibly by cascade deletion from map/system/character removal,
|
|
# auto-expiry, or concurrent cancellation). Broadcast cancellation so frontend updates.
|
|
Impl.broadcast!(map_id, :ping_cancelled, %{
|
|
id: ping_id,
|
|
solar_system_id: nil,
|
|
type: type
|
|
})
|
|
|
|
:ok
|
|
|
|
{:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]}} ->
|
|
# Same as above, but Ash wraps NotFound inside Invalid in some cases
|
|
Impl.broadcast!(map_id, :ping_cancelled, %{
|
|
id: ping_id,
|
|
solar_system_id: nil,
|
|
type: type
|
|
})
|
|
|
|
:ok
|
|
|
|
other ->
|
|
Logger.error(
|
|
"Failed to cancel ping #{ping_id}: unexpected result from get_by_id: #{inspect(other, pretty: true)}"
|
|
)
|
|
end
|
|
end
|
|
end
|