mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-10 17:55:43 +00:00
255 lines
7.0 KiB
Elixir
255 lines
7.0 KiB
Elixir
defmodule WandererApp.Character do
|
|
@moduledoc false
|
|
|
|
require Logger
|
|
|
|
@read_character_wallet_scope "esi-wallet.read_character_wallet.v1"
|
|
@read_corp_wallet_scope "esi-wallet.read_corporation_wallets.v1"
|
|
|
|
def get_character(character_id) when not is_nil(character_id) do
|
|
case Cachex.get(:character_cache, character_id) do
|
|
{:ok, nil} ->
|
|
case WandererApp.Api.Character.by_id(character_id) do
|
|
{:ok, character} ->
|
|
Cachex.put(:character_cache, character_id, character)
|
|
{:ok, character}
|
|
|
|
_ ->
|
|
{:error, :not_found}
|
|
end
|
|
|
|
{:ok, character} ->
|
|
{:ok, character}
|
|
end
|
|
end
|
|
|
|
def get_character(_character_id), do: {:ok, nil}
|
|
|
|
def get_character!(character_id) do
|
|
case get_character(character_id) do
|
|
{:ok, character} ->
|
|
character
|
|
|
|
_ ->
|
|
Logger.error("Failed to get character #{character_id}")
|
|
nil
|
|
end
|
|
end
|
|
|
|
def get_character_eve_ids!(character_ids),
|
|
do:
|
|
character_ids
|
|
|> Enum.map(fn character_id ->
|
|
character_id |> get_character!() |> Map.get(:eve_id)
|
|
end)
|
|
|
|
def update_character(character_id, character_update) do
|
|
Cachex.get_and_update(:character_cache, character_id, fn character ->
|
|
case character do
|
|
nil ->
|
|
case WandererApp.Api.Character.by_id(character_id) do
|
|
{:ok, character} ->
|
|
{:commit, Map.merge(character, character_update)}
|
|
|
|
_ ->
|
|
{:ignore, nil}
|
|
end
|
|
|
|
_ ->
|
|
{:commit, Map.merge(character, character_update)}
|
|
end
|
|
end)
|
|
end
|
|
|
|
def get_character_state(character_id) do
|
|
case Cachex.get(:character_state_cache, character_id) do
|
|
{:ok, nil} ->
|
|
character_state = WandererApp.Character.Tracker.init(character_id: character_id)
|
|
Cachex.put(:character_state_cache, character_id, character_state)
|
|
{:ok, character_state}
|
|
|
|
{:ok, character_state} ->
|
|
{:ok, character_state}
|
|
end
|
|
end
|
|
|
|
def get_character_state!(character_id) do
|
|
case get_character_state(character_id) do
|
|
{:ok, character_state} ->
|
|
character_state
|
|
|
|
_ ->
|
|
Logger.error("Failed to get character_state #{character_id}")
|
|
throw("Failed to get character_state #{character_id}")
|
|
end
|
|
end
|
|
|
|
def update_character_state(character_id, character_state_update) do
|
|
Cachex.get_and_update(:character_state_cache, character_id, fn character_state ->
|
|
case character_state do
|
|
nil ->
|
|
new_state = WandererApp.Character.Tracker.init(character_id: character_id)
|
|
:telemetry.execute([:wanderer_app, :character, :tracker, :started], %{count: 1})
|
|
|
|
{:commit, Map.merge(new_state, character_state_update)}
|
|
|
|
_ ->
|
|
{:commit, Map.merge(character_state, character_state_update)}
|
|
end
|
|
end)
|
|
end
|
|
|
|
def delete_character_state(character_id) do
|
|
Cachex.del(:character_state_cache, character_id)
|
|
end
|
|
|
|
def set_autopilot_waypoint(
|
|
character_id,
|
|
destination_id,
|
|
opts
|
|
) do
|
|
{:ok, %{access_token: access_token}} = WandererApp.Character.get_character(character_id)
|
|
|
|
WandererApp.Esi.set_autopilot_waypoint(
|
|
opts[:add_to_beginning],
|
|
opts[:clear_other_waypoints],
|
|
destination_id,
|
|
access_token: access_token
|
|
)
|
|
|
|
:ok
|
|
end
|
|
|
|
def search(character_id, opts \\ []) do
|
|
{:ok, %{access_token: access_token, eve_id: eve_id} = _character} =
|
|
get_character(character_id)
|
|
|
|
case WandererApp.Esi.search(eve_id |> String.to_integer(),
|
|
access_token: access_token,
|
|
character_id: character_id,
|
|
refresh_token?: true,
|
|
params: opts[:params]
|
|
) do
|
|
{:ok, result} ->
|
|
{:ok, result |> _prepare_search_results()}
|
|
|
|
{:error, error} ->
|
|
Logger.warning("#{__MODULE__} failed search: #{inspect(error)}")
|
|
{:ok, []}
|
|
end
|
|
end
|
|
|
|
def can_track_wallet?(%{scopes: scopes} = _character) when not is_nil(scopes) do
|
|
scopes |> String.split(" ") |> Enum.member?(@read_character_wallet_scope)
|
|
end
|
|
|
|
def can_track_wallet?(_), do: false
|
|
|
|
def can_track_corp_wallet?(%{scopes: scopes} = _character) when not is_nil(scopes) do
|
|
scopes |> String.split(" ") |> Enum.member?(@read_corp_wallet_scope)
|
|
end
|
|
|
|
def can_track_corp_wallet?(_), do: false
|
|
|
|
def get_ship(%{ship: ship_type_id, ship_name: ship_name} = _character)
|
|
when not is_nil(ship_type_id) and is_integer(ship_type_id) do
|
|
ship_type_id
|
|
|> WandererApp.CachedInfo.get_ship_type()
|
|
|> case do
|
|
{:ok, ship_type_info} when not is_nil(ship_type_info) ->
|
|
%{ship_type_id: ship_type_id, ship_name: ship_name, ship_type_info: ship_type_info}
|
|
|
|
_ ->
|
|
%{ship_type_id: ship_type_id, ship_name: ship_name, ship_type_info: %{}}
|
|
end
|
|
end
|
|
|
|
def get_ship(%{ship_name: ship_name} = _character) when is_binary(ship_name),
|
|
do: %{ship_name: ship_name, ship_type_info: %{}}
|
|
|
|
def get_ship(_),
|
|
do: %{ship_name: nil, ship_type_info: %{}}
|
|
|
|
def get_location(
|
|
%{solar_system_id: solar_system_id, structure_id: structure_id} =
|
|
_character
|
|
) do
|
|
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
|
|
{:ok, system_static_info} when not is_nil(system_static_info) ->
|
|
%{
|
|
solar_system_id: solar_system_id,
|
|
structure_id: structure_id,
|
|
solar_system_info: system_static_info
|
|
}
|
|
|
|
_ ->
|
|
%{
|
|
solar_system_id: solar_system_id,
|
|
structure_id: structure_id,
|
|
solar_system_info: %{}
|
|
}
|
|
end
|
|
end
|
|
|
|
defp _prepare_search_results(result) do
|
|
{:ok, characters} =
|
|
_load_eve_info(Map.get(result, "character"), :get_character_info, &_map_character_info/1)
|
|
|
|
{:ok, corporations} =
|
|
_load_eve_info(
|
|
Map.get(result, "corporation"),
|
|
:get_corporation_info,
|
|
&_map_corporation_info/1
|
|
)
|
|
|
|
{:ok, alliances} =
|
|
_load_eve_info(Map.get(result, "alliance"), :get_alliance_info, &_map_alliance_info/1)
|
|
|
|
[[characters | corporations] | alliances] |> List.flatten()
|
|
end
|
|
|
|
defp _load_eve_info(nil, _, _), do: {:ok, []}
|
|
|
|
defp _load_eve_info([], _, _), do: {:ok, []}
|
|
|
|
defp _load_eve_info(eve_ids, method, map_function),
|
|
do:
|
|
{:ok,
|
|
Enum.map(eve_ids, fn eve_id ->
|
|
Task.async(fn -> apply(WandererApp.Esi.ApiClient, method, [eve_id]) end)
|
|
end)
|
|
# 145000 == Timeout in milliseconds
|
|
|> Enum.map(fn task -> Task.await(task, 145_000) end)
|
|
|> Enum.map(fn result ->
|
|
case result do
|
|
{:ok, result} -> map_function.(result)
|
|
_ -> nil
|
|
end
|
|
end)
|
|
|> Enum.filter(fn result -> not is_nil(result) end)}
|
|
|
|
defp _map_alliance_info(info) do
|
|
%{
|
|
label: info["name"],
|
|
value: info["eve_id"] |> to_string(),
|
|
alliance: true
|
|
}
|
|
end
|
|
|
|
defp _map_character_info(info) do
|
|
%{
|
|
label: info["name"],
|
|
value: info["eve_id"] |> to_string(),
|
|
character: true
|
|
}
|
|
end
|
|
|
|
defp _map_corporation_info(info) do
|
|
%{
|
|
label: info["name"],
|
|
value: info["eve_id"] |> to_string(),
|
|
corporation: true
|
|
}
|
|
end
|
|
end
|