mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-11-26 02:53:49 +00:00
Compare commits
3 Commits
v1.15.0
...
map-events
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1f1098df6 | ||
|
|
ed5d824c0a | ||
|
|
d8e4631981 |
64
CHANGELOG.md
64
CHANGELOG.md
@@ -1,70 +1,6 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
<!-- changelog -->
|
<!-- changelog -->
|
||||||
|
|
||||||
## [v1.15.0](https://github.com/wanderer-industries/wanderer/compare/v1.14.1...v1.15.0) (2024-11-07)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Features:
|
|
||||||
|
|
||||||
* Connections: Add connection mark EOL time (#56)
|
|
||||||
|
|
||||||
## [v1.14.1](https://github.com/wanderer-industries/wanderer/compare/v1.14.0...v1.14.1) (2024-11-06)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes:
|
|
||||||
|
|
||||||
* Core: Fix character tracking permissions
|
|
||||||
|
|
||||||
## [v1.14.0](https://github.com/wanderer-industries/wanderer/compare/v1.13.12...v1.14.0) (2024-11-05)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Features:
|
|
||||||
|
|
||||||
* ACL: Add an ability to assign member role without DnD
|
|
||||||
|
|
||||||
## [v1.13.12](https://github.com/wanderer-industries/wanderer/compare/v1.13.11...v1.13.12) (2024-11-04)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes:
|
|
||||||
|
|
||||||
* Map: Fix system revert issues
|
|
||||||
|
|
||||||
## [v1.13.11](https://github.com/wanderer-industries/wanderer/compare/v1.13.10...v1.13.11) (2024-11-02)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes:
|
|
||||||
|
|
||||||
* Map: Fix system revert issues
|
|
||||||
|
|
||||||
## [v1.13.10](https://github.com/wanderer-industries/wanderer/compare/v1.13.9...v1.13.10) (2024-11-01)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes:
|
|
||||||
|
|
||||||
* Map: Fix system revert issues
|
|
||||||
|
|
||||||
## [v1.13.9](https://github.com/wanderer-industries/wanderer/compare/v1.13.8...v1.13.9) (2024-11-01)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [v1.13.8](https://github.com/wanderer-industries/wanderer/compare/v1.13.7...v1.13.8) (2024-10-28)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [v1.13.0](https://github.com/wanderer-industries/wanderer/compare/v1.12.11...v1.13.0) (2024-10-28)
|
## [v1.13.0](https://github.com/wanderer-industries/wanderer/compare/v1.12.11...v1.13.0) (2024-10-28)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
import classes from './Connections.module.scss';
|
import classes from './Connections.module.scss';
|
||||||
import { Sidebar } from 'primereact/sidebar';
|
import { Sidebar } from 'primereact/sidebar';
|
||||||
import { useEffect, useMemo, useState, useCallback } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||||
import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
|
import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import {
|
import { ConnectionOutput, OutCommand, Passage, SolarSystemConnection } from '@/hooks/Mapper/types';
|
||||||
ConnectionOutput,
|
|
||||||
ConnectionInfoOutput,
|
|
||||||
OutCommand,
|
|
||||||
Passage,
|
|
||||||
SolarSystemConnection,
|
|
||||||
} from '@/hooks/Mapper/types';
|
|
||||||
import { PassageCard } from './PassageCard';
|
import { PassageCard } from './PassageCard';
|
||||||
import { InfoDrawer, SystemView } from '@/hooks/Mapper/components/ui-kit';
|
import { InfoDrawer, SystemView } from '@/hooks/Mapper/components/ui-kit';
|
||||||
import { kgToTons } from '@/hooks/Mapper/utils/kgToTons.ts';
|
import { kgToTons } from '@/hooks/Mapper/utils/kgToTons.ts';
|
||||||
import { TimeAgo } from '@/hooks/Mapper/components/ui-kit';
|
|
||||||
|
|
||||||
const sortByDate = (a: string, b: string) => new Date(a).getTime() - new Date(b).getTime();
|
const sortByDate = (a: string, b: string) => new Date(a).getTime() - new Date(b).getTime();
|
||||||
|
|
||||||
@@ -76,44 +69,25 @@ export const Connections = ({ selectedConnection, onHide }: OnTheMapProps) => {
|
|||||||
}, [connections, selectedConnection]);
|
}, [connections, selectedConnection]);
|
||||||
|
|
||||||
const [passages, setPassages] = useState<Passage[]>([]);
|
const [passages, setPassages] = useState<Passage[]>([]);
|
||||||
const [info, setInfo] = useState<ConnectionInfoOutput>(null);
|
|
||||||
|
|
||||||
const loadInfo = useCallback(
|
|
||||||
async (connection: SolarSystemConnection) => {
|
|
||||||
const result = await outCommand<ConnectionInfoOutput>({
|
|
||||||
type: OutCommand.getConnectionInfo,
|
|
||||||
data: {
|
|
||||||
from: connection.source,
|
|
||||||
to: connection.target,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setInfo(result);
|
|
||||||
},
|
|
||||||
[outCommand],
|
|
||||||
);
|
|
||||||
|
|
||||||
const loadPassages = useCallback(
|
|
||||||
async (connection: SolarSystemConnection) => {
|
|
||||||
const result = await outCommand<ConnectionOutput>({
|
|
||||||
type: OutCommand.getPassages,
|
|
||||||
data: {
|
|
||||||
from: connection.source,
|
|
||||||
to: connection.target,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setPassages(result.passages.sort((a, b) => sortByDate(b.inserted_at, a.inserted_at)));
|
|
||||||
},
|
|
||||||
[outCommand],
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedConnection) {
|
if (!selectedConnection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadInfo(selectedConnection);
|
|
||||||
loadPassages(selectedConnection);
|
const loadInfo = async () => {
|
||||||
|
const result = await outCommand<ConnectionOutput>({
|
||||||
|
type: OutCommand.getPassages,
|
||||||
|
data: {
|
||||||
|
from: selectedConnection.source,
|
||||||
|
to: selectedConnection.target,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
setPassages(result.passages.sort((a, b) => sortByDate(b.inserted_at, a.inserted_at)));
|
||||||
|
};
|
||||||
|
|
||||||
|
loadInfo();
|
||||||
}, [selectedConnection]);
|
}, [selectedConnection]);
|
||||||
|
|
||||||
const approximateMass = useMemo(() => {
|
const approximateMass = useMemo(() => {
|
||||||
@@ -158,10 +132,6 @@ export const Connections = ({ selectedConnection, onHide }: OnTheMapProps) => {
|
|||||||
{kgToTons(approximateMass)}
|
{kgToTons(approximateMass)}
|
||||||
</InfoDrawer>
|
</InfoDrawer>
|
||||||
|
|
||||||
<InfoDrawer title="Mark EOL Time" rightSide>
|
|
||||||
{info?.marl_eol_time ? <TimeAgo timestamp={info.marl_eol_time} /> : ' unknown '}
|
|
||||||
</InfoDrawer>
|
|
||||||
|
|
||||||
<div className="flex gap-2"></div>
|
<div className="flex gap-2"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ export type Passage = {
|
|||||||
character: PassageLimitedCharacterType;
|
character: PassageLimitedCharacterType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ConnectionInfoOutput = {
|
|
||||||
marl_eol_time: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ConnectionOutput = {
|
export type ConnectionOutput = {
|
||||||
passages: Passage[];
|
passages: Passage[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ export enum OutCommand {
|
|||||||
getCharacterJumps = 'get_character_jumps',
|
getCharacterJumps = 'get_character_jumps',
|
||||||
getSignatures = 'get_signatures',
|
getSignatures = 'get_signatures',
|
||||||
getSystemStaticInfos = 'get_system_static_infos',
|
getSystemStaticInfos = 'get_system_static_infos',
|
||||||
getConnectionInfo = 'get_connection_info',
|
|
||||||
updateConnectionTimeStatus = 'update_connection_time_status',
|
updateConnectionTimeStatus = 'update_connection_time_status',
|
||||||
updateConnectionMassStatus = 'update_connection_mass_status',
|
updateConnectionMassStatus = 'update_connection_mass_status',
|
||||||
updateConnectionShipSizeType = 'update_connection_ship_size_type',
|
updateConnectionShipSizeType = 'update_connection_ship_size_type',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default {
|
|||||||
const selector = '#' + this.el.id;
|
const selector = '#' + this.el.id;
|
||||||
|
|
||||||
const droppable = new Droppable(containers, {
|
const droppable = new Droppable(containers, {
|
||||||
delay: 100,
|
delay: 150,
|
||||||
draggable: '.draggable',
|
draggable: '.draggable',
|
||||||
dropzone: '.dropzone',
|
dropzone: '.dropzone',
|
||||||
mirror: {
|
mirror: {
|
||||||
|
|||||||
@@ -138,7 +138,6 @@ config :ueberauth, WandererApp.Ueberauth.Strategy.Eve.OAuth,
|
|||||||
System.get_env("EVE_CLIENT_WITH_CORP_WALLET_SECRET", "<EVE_CLIENT_WITH_CORP_WALLET_SECRET>")
|
System.get_env("EVE_CLIENT_WITH_CORP_WALLET_SECRET", "<EVE_CLIENT_WITH_CORP_WALLET_SECRET>")
|
||||||
|
|
||||||
config :logger,
|
config :logger,
|
||||||
truncate: :infinity,
|
|
||||||
level:
|
level:
|
||||||
String.to_existing_atom(
|
String.to_existing_atom(
|
||||||
System.get_env(
|
System.get_env(
|
||||||
|
|||||||
3
fly.toml
3
fly.toml
@@ -6,7 +6,6 @@
|
|||||||
app = 'wanderer'
|
app = 'wanderer'
|
||||||
primary_region = 'ams'
|
primary_region = 'ams'
|
||||||
kill_signal = 'SIGTERM'
|
kill_signal = 'SIGTERM'
|
||||||
swap_size_mb = 512
|
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
|
|
||||||
@@ -36,6 +35,6 @@ path = "/metrics"
|
|||||||
soft_limit = 1000
|
soft_limit = 1000
|
||||||
|
|
||||||
[[vm]]
|
[[vm]]
|
||||||
memory = '256mb'
|
memory = '1gb'
|
||||||
cpu_kind = 'shared'
|
cpu_kind = 'shared'
|
||||||
cpus = 1
|
cpus = 1
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ defmodule WandererApp.Api.Calculations.CalcMapPermissions do
|
|||||||
use Ash.Resource.Calculation
|
use Ash.Resource.Calculation
|
||||||
require Ash.Query
|
require Ash.Query
|
||||||
|
|
||||||
|
import Bitwise
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def load(_query, _opts, _context) do
|
def load(_query, _opts, _context) do
|
||||||
[
|
[
|
||||||
@@ -15,8 +17,116 @@ defmodule WandererApp.Api.Calculations.CalcMapPermissions do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def calculate([record], _opts, %{actor: actor}),
|
def calculate([record], _opts, %{actor: actor}) do
|
||||||
do: WandererApp.Permissions.check_characters_access(actor.characters, record.acls)
|
characters = actor.characters
|
||||||
|
|
||||||
|
character_ids = characters |> Enum.map(& &1.id)
|
||||||
|
character_eve_ids = characters |> Enum.map(& &1.eve_id)
|
||||||
|
|
||||||
|
character_corporation_ids =
|
||||||
|
characters |> Enum.map(& &1.corporation_id) |> Enum.map(&to_string/1)
|
||||||
|
|
||||||
|
character_alliance_ids = characters |> Enum.map(& &1.alliance_id) |> Enum.map(&to_string/1)
|
||||||
|
|
||||||
|
result =
|
||||||
|
record.acls
|
||||||
|
|> Enum.reduce([0, 0], fn acl, acc ->
|
||||||
|
is_owner? = acl.owner_id in character_ids
|
||||||
|
|
||||||
|
is_character_member? =
|
||||||
|
acl.members |> Enum.any?(fn member -> member.eve_character_id in character_eve_ids end)
|
||||||
|
|
||||||
|
is_corporation_member? =
|
||||||
|
acl.members
|
||||||
|
|> Enum.any?(fn member -> member.eve_corporation_id in character_corporation_ids end)
|
||||||
|
|
||||||
|
is_alliance_member? =
|
||||||
|
acl.members
|
||||||
|
|> Enum.any?(fn member -> member.eve_alliance_id in character_alliance_ids end)
|
||||||
|
|
||||||
|
if is_owner? || is_character_member? || is_corporation_member? || is_alliance_member? do
|
||||||
|
case acc do
|
||||||
|
[_, -1] ->
|
||||||
|
[-1, -1]
|
||||||
|
|
||||||
|
[-1, char_acc] ->
|
||||||
|
char_acl_mask =
|
||||||
|
acl.members
|
||||||
|
|> Enum.filter(fn member ->
|
||||||
|
member.eve_character_id in character_eve_ids
|
||||||
|
end)
|
||||||
|
|> Enum.reduce(0, fn member, acc ->
|
||||||
|
case acc do
|
||||||
|
-1 -> -1
|
||||||
|
_ -> WandererApp.Permissions.calc_role_mask(member.role, acc)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
char_acc =
|
||||||
|
case char_acl_mask do
|
||||||
|
-1 -> -1
|
||||||
|
_ -> char_acc ||| char_acl_mask
|
||||||
|
end
|
||||||
|
|
||||||
|
[-1, char_acc]
|
||||||
|
|
||||||
|
[any_acc, char_acc] ->
|
||||||
|
any_acl_mask =
|
||||||
|
acl.members
|
||||||
|
|> Enum.filter(fn member ->
|
||||||
|
member.eve_character_id in character_eve_ids ||
|
||||||
|
member.eve_corporation_id in character_corporation_ids ||
|
||||||
|
member.eve_alliance_id in character_alliance_ids
|
||||||
|
end)
|
||||||
|
|> Enum.reduce(0, fn member, acc ->
|
||||||
|
case acc do
|
||||||
|
-1 -> -1
|
||||||
|
_ -> WandererApp.Permissions.calc_role_mask(member.role, acc)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
char_acl_mask =
|
||||||
|
acl.members
|
||||||
|
|> Enum.filter(fn member ->
|
||||||
|
member.eve_character_id in character_eve_ids
|
||||||
|
end)
|
||||||
|
|> Enum.reduce(0, fn member, acc ->
|
||||||
|
case acc do
|
||||||
|
-1 -> -1
|
||||||
|
_ -> WandererApp.Permissions.calc_role_mask(member.role, acc)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
any_acc =
|
||||||
|
case any_acl_mask do
|
||||||
|
-1 -> -1
|
||||||
|
_ -> any_acc ||| any_acl_mask
|
||||||
|
end
|
||||||
|
|
||||||
|
char_acc =
|
||||||
|
case char_acl_mask do
|
||||||
|
-1 -> -1
|
||||||
|
_ -> char_acc ||| char_acl_mask
|
||||||
|
end
|
||||||
|
|
||||||
|
[any_acc, char_acc]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
case result do
|
||||||
|
[_, -1] ->
|
||||||
|
[-1]
|
||||||
|
|
||||||
|
[-1, char_acc] ->
|
||||||
|
[char_acc]
|
||||||
|
|
||||||
|
[any_acc, _char_acc] ->
|
||||||
|
[any_acc]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def calculate(_records, _opts, _context) do
|
def calculate(_records, _opts, _context) do
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ defmodule WandererApp.Application do
|
|||||||
|
|
||||||
use Application
|
use Application
|
||||||
|
|
||||||
require Logger
|
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
children =
|
children =
|
||||||
@@ -47,16 +45,7 @@ defmodule WandererApp.Application do
|
|||||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||||
# for other strategies and supported options
|
# for other strategies and supported options
|
||||||
opts = [strategy: :one_for_one, name: WandererApp.Supervisor]
|
opts = [strategy: :one_for_one, name: WandererApp.Supervisor]
|
||||||
|
|
||||||
Supervisor.start_link(children, opts)
|
Supervisor.start_link(children, opts)
|
||||||
|> case do
|
|
||||||
{:ok, _pid} = ok ->
|
|
||||||
ok
|
|
||||||
|
|
||||||
{:error, info} = e ->
|
|
||||||
Logger.error("Failed to start application: #{inspect(info)}")
|
|
||||||
e
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Tell Phoenix to update the endpoint configuration
|
# Tell Phoenix to update the endpoint configuration
|
||||||
|
|||||||
@@ -37,32 +37,32 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
|
|
||||||
@logger Application.compile_env(:wanderer_app, :logger)
|
@logger Application.compile_env(:wanderer_app, :logger)
|
||||||
|
|
||||||
def get_server_status, do: get("/status")
|
def get_server_status, do: _get("/status")
|
||||||
|
|
||||||
def set_autopilot_waypoint(add_to_beginning, clear_other_waypoints, destination_id, opts \\ []),
|
def set_autopilot_waypoint(add_to_beginning, clear_other_waypoints, destination_id, opts \\ []) do
|
||||||
do:
|
_post_esi(
|
||||||
post_esi(
|
"/ui/autopilot/waypoint",
|
||||||
"/ui/autopilot/waypoint",
|
opts
|
||||||
opts
|
|> Keyword.merge(
|
||||||
|> Keyword.merge(
|
params: %{
|
||||||
params: %{
|
add_to_beginning: add_to_beginning,
|
||||||
add_to_beginning: add_to_beginning,
|
clear_other_waypoints: clear_other_waypoints,
|
||||||
clear_other_waypoints: clear_other_waypoints,
|
destination_id: destination_id
|
||||||
destination_id: destination_id
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def post_characters_affiliation(character_eve_ids, _opts)
|
def post_characters_affiliation(character_eve_ids, _opts)
|
||||||
when is_list(character_eve_ids),
|
when is_list(character_eve_ids) do
|
||||||
do:
|
_post(
|
||||||
post(
|
"#{@base_url}/characters/affiliation/",
|
||||||
"#{@base_url}/characters/affiliation/",
|
json: character_eve_ids,
|
||||||
json: character_eve_ids,
|
params: %{
|
||||||
params: %{
|
datasource: "tranquility"
|
||||||
datasource: "tranquility"
|
}
|
||||||
}
|
)
|
||||||
)
|
end
|
||||||
|
|
||||||
def find_routes(map_id, origin, hubs, routes_settings) do
|
def find_routes(map_id, origin, hubs, routes_settings) do
|
||||||
origin = origin |> String.to_integer()
|
origin = origin |> String.to_integer()
|
||||||
@@ -184,7 +184,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
routes =
|
routes =
|
||||||
all_routes
|
all_routes
|
||||||
|> Enum.map(fn route_info ->
|
|> Enum.map(fn route_info ->
|
||||||
map_route_info(route_info)
|
_map_route_info(route_info)
|
||||||
end)
|
end)
|
||||||
|> Enum.filter(fn route_info -> not is_nil(route_info) end)
|
|> Enum.filter(fn route_info -> not is_nil(route_info) end)
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
{:ok, result}
|
{:ok, result}
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
case get_all_routes_custom(hubs, origin, params) do
|
case _get_all_routes_custom(hubs, origin, params) do
|
||||||
{:ok, result} ->
|
{:ok, result} ->
|
||||||
WandererApp.Cache.insert(
|
WandererApp.Cache.insert(
|
||||||
cache_key,
|
cache_key,
|
||||||
@@ -210,21 +210,22 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
|
|
||||||
{:ok, result}
|
{:ok, result}
|
||||||
|
|
||||||
{:error, _error} ->
|
{:error, error} ->
|
||||||
|
@logger.error("Error getting custom routes for #{inspect(origin)}: #{inspect(error)}")
|
||||||
@logger.error("Error getting custom routes for #{inspect(origin)}: #{inspect(hubs)}")
|
@logger.error("Error getting custom routes for #{inspect(origin)}: #{inspect(hubs)}")
|
||||||
|
|
||||||
@logger.error(
|
@logger.error(
|
||||||
"Error getting custom routes for #{inspect(origin)}: #{inspect(params)}"
|
"Error getting custom routes for #{inspect(origin)}: #{inspect(params)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
get_all_routes_eve(hubs, origin, params, opts)
|
_get_all_routes_eve(hubs, origin, params, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_all_routes_custom(hubs, origin, params),
|
defp _get_all_routes_custom(hubs, origin, params),
|
||||||
do:
|
do:
|
||||||
post(
|
_post(
|
||||||
"#{get_custom_route_base_url()}/route/multiple",
|
"#{get_custom_route_base_url()}/route/multiple",
|
||||||
[
|
[
|
||||||
json: %{
|
json: %{
|
||||||
@@ -238,7 +239,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
|> Keyword.merge(@timeout_opts)
|
|> Keyword.merge(@timeout_opts)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_all_routes_eve(hubs, origin, params, opts),
|
def _get_all_routes_eve(hubs, origin, params, opts),
|
||||||
do:
|
do:
|
||||||
{:ok,
|
{:ok,
|
||||||
hubs
|
hubs
|
||||||
@@ -307,7 +308,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
opts: [ttl: @ttl]
|
opts: [ttl: @ttl]
|
||||||
)
|
)
|
||||||
def get_character_info(eve_id, opts \\ []) do
|
def get_character_info(eve_id, opts \\ []) do
|
||||||
case get(
|
case _get(
|
||||||
"/characters/#{eve_id}/",
|
"/characters/#{eve_id}/",
|
||||||
opts |> _with_cache_opts()
|
opts |> _with_cache_opts()
|
||||||
) do
|
) do
|
||||||
@@ -384,7 +385,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
|
|
||||||
defp _get_routes_eve(origin, destination, params, opts),
|
defp _get_routes_eve(origin, destination, params, opts),
|
||||||
do:
|
do:
|
||||||
get(
|
_get(
|
||||||
"/route/#{origin}/#{destination}/?#{params |> Plug.Conn.Query.encode()}",
|
"/route/#{origin}/#{destination}/?#{params |> Plug.Conn.Query.encode()}",
|
||||||
opts |> _with_cache_opts()
|
opts |> _with_cache_opts()
|
||||||
)
|
)
|
||||||
@@ -393,14 +394,14 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
|
|
||||||
defp _get_alliance_info(alliance_eve_id, info_path, opts),
|
defp _get_alliance_info(alliance_eve_id, info_path, opts),
|
||||||
do:
|
do:
|
||||||
get(
|
_get(
|
||||||
"/alliances/#{alliance_eve_id}/#{info_path}",
|
"/alliances/#{alliance_eve_id}/#{info_path}",
|
||||||
opts |> _with_cache_opts()
|
opts |> _with_cache_opts()
|
||||||
)
|
)
|
||||||
|
|
||||||
defp _get_corporation_info(corporation_eve_id, info_path, opts),
|
defp _get_corporation_info(corporation_eve_id, info_path, opts),
|
||||||
do:
|
do:
|
||||||
get(
|
_get(
|
||||||
"/corporations/#{corporation_eve_id}/#{info_path}",
|
"/corporations/#{corporation_eve_id}/#{info_path}",
|
||||||
opts |> _with_cache_opts()
|
opts |> _with_cache_opts()
|
||||||
)
|
)
|
||||||
@@ -415,7 +416,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
character_id = opts |> Keyword.get(:character_id, nil)
|
character_id = opts |> Keyword.get(:character_id, nil)
|
||||||
|
|
||||||
if not _is_access_token_expired?(character_id) do
|
if not _is_access_token_expired?(character_id) do
|
||||||
get(
|
_get(
|
||||||
path,
|
path,
|
||||||
auth_opts,
|
auth_opts,
|
||||||
opts
|
opts
|
||||||
@@ -436,7 +437,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
|
|
||||||
defp _get_corporation_auth_data(corporation_eve_id, info_path, opts),
|
defp _get_corporation_auth_data(corporation_eve_id, info_path, opts),
|
||||||
do:
|
do:
|
||||||
get(
|
_get(
|
||||||
"/corporations/#{corporation_eve_id}/#{info_path}",
|
"/corporations/#{corporation_eve_id}/#{info_path}",
|
||||||
[params: opts[:params] || []] ++
|
[params: opts[:params] || []] ++
|
||||||
(opts |> _get_auth_opts() |> _with_cache_opts()),
|
(opts |> _get_auth_opts() |> _with_cache_opts()),
|
||||||
@@ -447,14 +448,14 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
opts |> Keyword.merge(@cache_opts) |> Keyword.merge(cache_dir: System.tmp_dir!())
|
opts |> Keyword.merge(@cache_opts) |> Keyword.merge(cache_dir: System.tmp_dir!())
|
||||||
end
|
end
|
||||||
|
|
||||||
defp post_esi(path, opts),
|
defp _post_esi(path, opts),
|
||||||
do:
|
do:
|
||||||
post(
|
_post(
|
||||||
"#{@base_url}#{path}",
|
"#{@base_url}#{path}",
|
||||||
[params: opts[:params] || []] ++ (opts |> _get_auth_opts())
|
[params: opts[:params] || []] ++ (opts |> _get_auth_opts())
|
||||||
)
|
)
|
||||||
|
|
||||||
defp get(path, api_opts \\ [], opts \\ []) do
|
defp _get(path, api_opts \\ [], opts \\ []) do
|
||||||
try do
|
try do
|
||||||
case Req.get("#{@base_url}#{path}", api_opts |> Keyword.merge(@retry_opts)) do
|
case Req.get("#{@base_url}#{path}", api_opts |> Keyword.merge(@retry_opts)) do
|
||||||
{:ok, %{status: 200, body: body}} ->
|
{:ok, %{status: 200, body: body}} ->
|
||||||
@@ -486,7 +487,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp post(url, opts) do
|
defp _post(url, opts) do
|
||||||
try do
|
try do
|
||||||
case Req.post("#{url}", opts) do
|
case Req.post("#{url}", opts) do
|
||||||
{:ok, %{status: status, body: body}} when status in [200, 201] ->
|
{:ok, %{status: status, body: body}} when status in [200, 201] ->
|
||||||
@@ -524,7 +525,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
{:ok, token} ->
|
{:ok, token} ->
|
||||||
auth_opts = [access_token: token.access_token] |> _get_auth_opts()
|
auth_opts = [access_token: token.access_token] |> _get_auth_opts()
|
||||||
|
|
||||||
get(
|
_get(
|
||||||
path,
|
path,
|
||||||
api_opts |> Keyword.merge(auth_opts),
|
api_opts |> Keyword.merge(auth_opts),
|
||||||
opts |> Keyword.merge(retry_count: retry_count + 1)
|
opts |> Keyword.merge(retry_count: retry_count + 1)
|
||||||
@@ -599,7 +600,7 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp map_route_info(
|
defp _map_route_info(
|
||||||
%{
|
%{
|
||||||
"origin" => origin,
|
"origin" => origin,
|
||||||
"destination" => destination,
|
"destination" => destination,
|
||||||
@@ -608,14 +609,14 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
} = _route_info
|
} = _route_info
|
||||||
),
|
),
|
||||||
do:
|
do:
|
||||||
map_route_info(%{
|
_map_route_info(%{
|
||||||
origin: origin,
|
origin: origin,
|
||||||
destination: destination,
|
destination: destination,
|
||||||
systems: result_systems,
|
systems: result_systems,
|
||||||
success: success
|
success: success
|
||||||
})
|
})
|
||||||
|
|
||||||
defp map_route_info(
|
defp _map_route_info(
|
||||||
%{origin: origin, destination: destination, systems: result_systems, success: success} =
|
%{origin: origin, destination: destination, systems: result_systems, success: success} =
|
||||||
_route_info
|
_route_info
|
||||||
) do
|
) do
|
||||||
@@ -637,5 +638,5 @@ defmodule WandererApp.Esi.ApiClient do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp map_route_info(_), do: nil
|
defp _map_route_info(_), do: nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ defmodule WandererApp.Map do
|
|||||||
defstruct map_id: nil,
|
defstruct map_id: nil,
|
||||||
name: nil,
|
name: nil,
|
||||||
scope: :none,
|
scope: :none,
|
||||||
owner_id: nil,
|
|
||||||
characters: [],
|
characters: [],
|
||||||
systems: Map.new(),
|
systems: Map.new(),
|
||||||
hubs: [],
|
hubs: [],
|
||||||
@@ -17,12 +16,11 @@ defmodule WandererApp.Map do
|
|||||||
characters_limit: nil,
|
characters_limit: nil,
|
||||||
hubs_limit: nil
|
hubs_limit: nil
|
||||||
|
|
||||||
def new(%{id: map_id, name: name, scope: scope, owner_id: owner_id, acls: acls, hubs: hubs}) do
|
def new(%{id: map_id, name: name, scope: scope, acls: acls, hubs: hubs}) do
|
||||||
map =
|
map =
|
||||||
struct!(__MODULE__,
|
struct!(__MODULE__,
|
||||||
map_id: map_id,
|
map_id: map_id,
|
||||||
scope: scope,
|
scope: scope,
|
||||||
owner_id: owner_id,
|
|
||||||
name: name,
|
name: name,
|
||||||
acls: acls,
|
acls: acls,
|
||||||
hubs: hubs
|
hubs: hubs
|
||||||
@@ -216,7 +214,7 @@ defmodule WandererApp.Map do
|
|||||||
%{visible: true} = system ->
|
%{visible: true} = system ->
|
||||||
system
|
system
|
||||||
|
|
||||||
_system ->
|
_ ->
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -264,7 +262,7 @@ defmodule WandererApp.Map do
|
|||||||
case not Map.has_key?(systems, solar_system_id) do
|
case not Map.has_key?(systems, solar_system_id) do
|
||||||
true ->
|
true ->
|
||||||
map_id
|
map_id
|
||||||
|> update_map(%{systems: Map.put(systems, solar_system_id, system)})
|
|> update_map(%{systems: Map.put_new(systems, solar_system_id, system)})
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
|
|
||||||
|
|||||||
@@ -183,12 +183,6 @@ defmodule WandererApp.Map.Server do
|
|||||||
|> map_pid!
|
|> map_pid!
|
||||||
|> GenServer.cast({&Impl.delete_connection/2, [connection_info]})
|
|> GenServer.cast({&Impl.delete_connection/2, [connection_info]})
|
||||||
|
|
||||||
def get_connection_info(map_id, connection_info) when is_binary(map_id),
|
|
||||||
do:
|
|
||||||
map_id
|
|
||||||
|> map_pid!
|
|
||||||
|> GenServer.call({&Impl.get_connection_info/2, [connection_info]}, :timer.minutes(1))
|
|
||||||
|
|
||||||
def update_connection_time_status(map_id, connection_info) when is_binary(map_id),
|
def update_connection_time_status(map_id, connection_info) when is_binary(map_id),
|
||||||
do:
|
do:
|
||||||
map_id
|
map_id
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
# @unknown 100_100
|
# @unknown 100_100
|
||||||
|
|
||||||
@systems_cleanup_timeout :timer.minutes(30)
|
@systems_cleanup_timeout :timer.minutes(30)
|
||||||
@characters_cleanup_timeout :timer.minutes(1)
|
|
||||||
@connections_cleanup_timeout :timer.minutes(2)
|
@connections_cleanup_timeout :timer.minutes(2)
|
||||||
|
|
||||||
@connection_time_status_eol 1
|
@connection_time_status_eol 1
|
||||||
@@ -113,28 +112,20 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_state(%__MODULE__{map_id: map_id} = state) do
|
def load_state(%__MODULE__{map_id: map_id} = state) do
|
||||||
with {:ok, map} <-
|
with {:ok, map} <- WandererApp.MapRepo.get(map_id, [:acls, :characters]),
|
||||||
WandererApp.MapRepo.get(map_id, [
|
|
||||||
:owner,
|
|
||||||
:characters,
|
|
||||||
acls: [
|
|
||||||
:owner_id,
|
|
||||||
members: [:role, :eve_character_id, :eve_corporation_id, :eve_alliance_id]
|
|
||||||
]
|
|
||||||
]),
|
|
||||||
{:ok, systems} <- WandererApp.MapSystemRepo.get_visible_by_map(map_id),
|
{:ok, systems} <- WandererApp.MapSystemRepo.get_visible_by_map(map_id),
|
||||||
{:ok, connections} <- WandererApp.MapConnectionRepo.get_by_map(map_id),
|
{:ok, connections} <- WandererApp.MapConnectionRepo.get_by_map(map_id),
|
||||||
{:ok, subscription_settings} <-
|
{:ok, subscription_settings} <-
|
||||||
WandererApp.Map.SubscriptionManager.get_active_map_subscription(map_id) do
|
WandererApp.Map.SubscriptionManager.get_active_map_subscription(map_id) do
|
||||||
state
|
state
|
||||||
|> init_map(
|
|> _init_map(
|
||||||
map,
|
map,
|
||||||
subscription_settings,
|
subscription_settings,
|
||||||
systems,
|
systems,
|
||||||
connections
|
connections
|
||||||
)
|
)
|
||||||
|> init_map_systems(systems)
|
|> _init_map_systems(systems)
|
||||||
|> init_map_cache()
|
|> _init_map_cache()
|
||||||
else
|
else
|
||||||
error ->
|
error ->
|
||||||
@logger.error("Failed to load map state: #{inspect(error, pretty: true)}")
|
@logger.error("Failed to load map state: #{inspect(error, pretty: true)}")
|
||||||
@@ -143,7 +134,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start_map(%__MODULE__{map: map, map_id: map_id} = state) do
|
def start_map(%__MODULE__{map: map, map_id: map_id} = state) do
|
||||||
with :ok <- track_acls(map.acls |> Enum.map(& &1.id)) do
|
with :ok <- _track_acls(map.acls |> Enum.map(& &1.id)) do
|
||||||
@pubsub_client.subscribe(
|
@pubsub_client.subscribe(
|
||||||
WandererApp.PubSub,
|
WandererApp.PubSub,
|
||||||
"maps:#{map_id}"
|
"maps:#{map_id}"
|
||||||
@@ -153,8 +144,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
Process.send_after(self(), :update_tracked_characters, 100)
|
Process.send_after(self(), :update_tracked_characters, 100)
|
||||||
Process.send_after(self(), :update_presence, @update_presence_timeout)
|
Process.send_after(self(), :update_presence, @update_presence_timeout)
|
||||||
Process.send_after(self(), :cleanup_connections, 5000)
|
Process.send_after(self(), :cleanup_connections, 5000)
|
||||||
Process.send_after(self(), :cleanup_systems, 10_000)
|
Process.send_after(self(), :cleanup_systems, 10000)
|
||||||
Process.send_after(self(), :cleanup_characters, :timer.minutes(5))
|
|
||||||
Process.send_after(self(), :backup_state, @backup_state_timeout)
|
Process.send_after(self(), :backup_state, @backup_state_timeout)
|
||||||
|
|
||||||
WandererApp.Cache.insert("map_#{map_id}:started", true)
|
WandererApp.Cache.insert("map_#{map_id}:started", true)
|
||||||
@@ -179,7 +169,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
:telemetry.execute([:wanderer_app, :map, :stopped], %{count: 1})
|
:telemetry.execute([:wanderer_app, :map, :stopped], %{count: 1})
|
||||||
|
|
||||||
state
|
state
|
||||||
|> maybe_stop_rtree()
|
|> _maybe_stop_rtree()
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_map(%{map: map} = _state), do: {:ok, map}
|
def get_map(%{map: map} = _state), do: {:ok, map}
|
||||||
@@ -259,37 +249,37 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state,
|
state,
|
||||||
update
|
update
|
||||||
),
|
),
|
||||||
do: state |> update_system(:update_name, [:name], update)
|
do: state |> _update_system(:update_name, [:name], update)
|
||||||
|
|
||||||
def update_system_description(
|
def update_system_description(
|
||||||
state,
|
state,
|
||||||
update
|
update
|
||||||
),
|
),
|
||||||
do: state |> update_system(:update_description, [:description], update)
|
do: state |> _update_system(:update_description, [:description], update)
|
||||||
|
|
||||||
def update_system_status(
|
def update_system_status(
|
||||||
state,
|
state,
|
||||||
update
|
update
|
||||||
),
|
),
|
||||||
do: state |> update_system(:update_status, [:status], update)
|
do: state |> _update_system(:update_status, [:status], update)
|
||||||
|
|
||||||
def update_system_tag(
|
def update_system_tag(
|
||||||
state,
|
state,
|
||||||
update
|
update
|
||||||
),
|
),
|
||||||
do: state |> update_system(:update_tag, [:tag], update)
|
do: state |> _update_system(:update_tag, [:tag], update)
|
||||||
|
|
||||||
def update_system_locked(
|
def update_system_locked(
|
||||||
state,
|
state,
|
||||||
update
|
update
|
||||||
),
|
),
|
||||||
do: state |> update_system(:update_locked, [:locked], update)
|
do: state |> _update_system(:update_locked, [:locked], update)
|
||||||
|
|
||||||
def update_system_labels(
|
def update_system_labels(
|
||||||
state,
|
state,
|
||||||
update
|
update
|
||||||
),
|
),
|
||||||
do: state |> update_system(:update_labels, [:labels], update)
|
do: state |> _update_system(:update_labels, [:labels], update)
|
||||||
|
|
||||||
def update_system_position(
|
def update_system_position(
|
||||||
%{rtree_name: rtree_name} = state,
|
%{rtree_name: rtree_name} = state,
|
||||||
@@ -297,7 +287,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
),
|
),
|
||||||
do:
|
do:
|
||||||
state
|
state
|
||||||
|> update_system(
|
|> _update_system(
|
||||||
:update_position,
|
:update_position,
|
||||||
[:position_x, :position_y],
|
[:position_x, :position_y],
|
||||||
update,
|
update,
|
||||||
@@ -445,34 +435,12 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_connection_info(
|
|
||||||
%{map_id: map_id} = _state,
|
|
||||||
%{
|
|
||||||
solar_system_source_id: solar_system_source_id,
|
|
||||||
solar_system_target_id: solar_system_target_id
|
|
||||||
} = _connection_info
|
|
||||||
) do
|
|
||||||
WandererApp.Map.find_connection(
|
|
||||||
map_id,
|
|
||||||
solar_system_source_id,
|
|
||||||
solar_system_target_id
|
|
||||||
)
|
|
||||||
|> case do
|
|
||||||
{:ok, %{id: connection_id}} ->
|
|
||||||
connection_mark_eol_time = get_connection_mark_eol_time(map_id, connection_id, nil)
|
|
||||||
{:ok, %{marl_eol_time: connection_mark_eol_time}}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:error, :not_found}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_connection_time_status(
|
def update_connection_time_status(
|
||||||
%{map_id: map_id} = state,
|
%{map_id: map_id} = state,
|
||||||
connection_update
|
connection_update
|
||||||
),
|
),
|
||||||
do:
|
do:
|
||||||
update_connection(state, :update_time_status, [:time_status], connection_update, fn
|
_update_connection(state, :update_time_status, [:time_status], connection_update, fn
|
||||||
%{id: connection_id, time_status: time_status} ->
|
%{id: connection_id, time_status: time_status} ->
|
||||||
case time_status == @connection_time_status_eol do
|
case time_status == @connection_time_status_eol do
|
||||||
true ->
|
true ->
|
||||||
@@ -491,25 +459,25 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state,
|
state,
|
||||||
connection_update
|
connection_update
|
||||||
),
|
),
|
||||||
do: update_connection(state, :update_mass_status, [:mass_status], connection_update)
|
do: _update_connection(state, :update_mass_status, [:mass_status], connection_update)
|
||||||
|
|
||||||
def update_connection_ship_size_type(
|
def update_connection_ship_size_type(
|
||||||
state,
|
state,
|
||||||
connection_update
|
connection_update
|
||||||
),
|
),
|
||||||
do: update_connection(state, :update_ship_size_type, [:ship_size_type], connection_update)
|
do: _update_connection(state, :update_ship_size_type, [:ship_size_type], connection_update)
|
||||||
|
|
||||||
def update_connection_locked(
|
def update_connection_locked(
|
||||||
state,
|
state,
|
||||||
connection_update
|
connection_update
|
||||||
),
|
),
|
||||||
do: update_connection(state, :update_locked, [:locked], connection_update)
|
do: _update_connection(state, :update_locked, [:locked], connection_update)
|
||||||
|
|
||||||
def update_connection_custom_info(
|
def update_connection_custom_info(
|
||||||
state,
|
state,
|
||||||
connection_update
|
connection_update
|
||||||
),
|
),
|
||||||
do: update_connection(state, :update_custom_info, [:custom_info], connection_update)
|
do: _update_connection(state, :update_custom_info, [:custom_info], connection_update)
|
||||||
|
|
||||||
def import_settings(%{map_id: map_id} = state, settings, user_id) do
|
def import_settings(%{map_id: map_id} = state, settings, user_id) do
|
||||||
WandererApp.Cache.put(
|
WandererApp.Cache.put(
|
||||||
@@ -519,9 +487,9 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
|
|
||||||
state =
|
state =
|
||||||
state
|
state
|
||||||
|> maybe_import_systems(settings, user_id, nil)
|
|> _maybe_import_systems(settings, user_id, nil)
|
||||||
|> maybe_import_connections(settings, user_id)
|
|> _maybe_import_connections(settings, user_id)
|
||||||
|> maybe_import_hubs(settings, user_id)
|
|> _maybe_import_hubs(settings, user_id)
|
||||||
|
|
||||||
WandererApp.Cache.take("map_#{map_id}:importing")
|
WandererApp.Cache.take("map_#{map_id}:importing")
|
||||||
|
|
||||||
@@ -541,11 +509,11 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
|> Enum.map(fn character_id ->
|
|> Enum.map(fn character_id ->
|
||||||
Task.start_link(fn ->
|
Task.start_link(fn ->
|
||||||
character_updates =
|
character_updates =
|
||||||
maybe_update_online(map_id, character_id) ++
|
_maybe_update_online(map_id, character_id) ++
|
||||||
maybe_update_location(map_id, character_id) ++
|
_maybe_update_location(map_id, character_id) ++
|
||||||
maybe_update_ship(map_id, character_id) ++
|
_maybe_update_ship(map_id, character_id) ++
|
||||||
maybe_update_alliance(map_id, character_id) ++
|
_maybe_update_alliance(map_id, character_id) ++
|
||||||
maybe_update_corporation(map_id, character_id)
|
_maybe_update_corporation(map_id, character_id)
|
||||||
|
|
||||||
character_updates
|
character_updates
|
||||||
|> Enum.filter(fn update -> update != :skip end)
|
|> Enum.filter(fn update -> update != :skip end)
|
||||||
@@ -553,7 +521,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
update
|
update
|
||||||
|> case do
|
|> case do
|
||||||
{:character_location, location_info, old_location_info} ->
|
{:character_location, location_info, old_location_info} ->
|
||||||
update_location(
|
_update_location(
|
||||||
character_id,
|
character_id,
|
||||||
location_info,
|
location_info,
|
||||||
old_location_info,
|
old_location_info,
|
||||||
@@ -569,25 +537,9 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
:broadcast
|
:broadcast
|
||||||
|
|
||||||
{:character_alliance, _info} ->
|
{:character_alliance, _info} ->
|
||||||
WandererApp.Cache.insert_or_update(
|
|
||||||
"map_#{map_id}:invalidate_character_ids",
|
|
||||||
[character_id],
|
|
||||||
fn ids ->
|
|
||||||
[character_id | ids]
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
:broadcast
|
:broadcast
|
||||||
|
|
||||||
{:character_corporation, _info} ->
|
{:character_corporation, _info} ->
|
||||||
WandererApp.Cache.insert_or_update(
|
|
||||||
"map_#{map_id}:invalidate_character_ids",
|
|
||||||
[character_id],
|
|
||||||
fn ids ->
|
|
||||||
[character_id | ids]
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
:broadcast
|
:broadcast
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
@@ -638,37 +590,29 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
def handle_event(:update_presence, %{map_id: map_id} = state) do
|
def handle_event(:update_presence, %{map_id: map_id} = state) do
|
||||||
Process.send_after(self(), :update_presence, @update_presence_timeout)
|
Process.send_after(self(), :update_presence, @update_presence_timeout)
|
||||||
|
|
||||||
update_presence(map_id)
|
_update_presence(map_id)
|
||||||
|
|
||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event(:backup_state, state) do
|
def handle_event(:backup_state, state) do
|
||||||
Process.send_after(self(), :backup_state, @backup_state_timeout)
|
Process.send_after(self(), :backup_state, @backup_state_timeout)
|
||||||
{:ok, _map_state} = state |> save_map_state()
|
{:ok, _map_state} = state |> _save_map_state()
|
||||||
|
|
||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event(
|
def handle_event({:map_acl_updated, added_acls, removed_acls}, %{map: old_map} = state) do
|
||||||
{:map_acl_updated, added_acls, removed_acls},
|
{:ok, map} = WandererApp.MapRepo.get(old_map.map_id, [:acls])
|
||||||
%{map_id: map_id, map: old_map} = state
|
|
||||||
) do
|
|
||||||
{:ok, map} =
|
|
||||||
WandererApp.MapRepo.get(map_id,
|
|
||||||
acls: [
|
|
||||||
:owner_id,
|
|
||||||
members: [:role, :eve_character_id, :eve_corporation_id, :eve_alliance_id]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
track_acls(added_acls)
|
_track_acls(added_acls)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
(added_acls ++ removed_acls)
|
[added_acls | removed_acls]
|
||||||
|
|> List.flatten()
|
||||||
|> Task.async_stream(
|
|> Task.async_stream(
|
||||||
fn acl_id ->
|
fn acl_id ->
|
||||||
update_acl(acl_id)
|
_update_acl(acl_id)
|
||||||
end,
|
end,
|
||||||
max_concurrency: 10,
|
max_concurrency: 10,
|
||||||
timeout: :timer.seconds(15)
|
timeout: :timer.seconds(15)
|
||||||
@@ -697,45 +641,29 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
}
|
}
|
||||||
|
|
||||||
error ->
|
error ->
|
||||||
@logger.error("Failed to update map #{map_id} acl: #{inspect(error, pretty: true)}")
|
@logger.error(
|
||||||
|
"Failed to update map #{old_map.map_id} acl: #{inspect(error, pretty: true)}"
|
||||||
|
)
|
||||||
|
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
map_update = %{acls: map.acls, scope: map.scope}
|
_broadcast_acl_updates({:ok, result})
|
||||||
|
|
||||||
WandererApp.Map.update_map(map_id, map_update)
|
%{state | map: %{old_map | acls: map.acls, scope: map.scope}}
|
||||||
|
|
||||||
broadcast_acl_updates({:ok, result}, map_id)
|
|
||||||
|
|
||||||
%{state | map: Map.merge(old_map, map_update)}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event({:acl_updated, %{acl_id: acl_id}}, %{map_id: map_id, map: old_map} = state) do
|
def handle_event({:acl_updated, %{acl_id: acl_id}}, %{map: map} = state) do
|
||||||
{:ok, map} =
|
|
||||||
WandererApp.MapRepo.get(map_id,
|
|
||||||
acls: [
|
|
||||||
:owner_id,
|
|
||||||
members: [:role, :eve_character_id, :eve_corporation_id, :eve_alliance_id]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
if map.acls |> Enum.map(& &1.id) |> Enum.member?(acl_id) do
|
if map.acls |> Enum.map(& &1.id) |> Enum.member?(acl_id) do
|
||||||
map_update = %{acls: map.acls}
|
|
||||||
|
|
||||||
WandererApp.Map.update_map(map_id, map_update)
|
|
||||||
|
|
||||||
:ok =
|
:ok =
|
||||||
acl_id
|
acl_id
|
||||||
|> update_acl()
|
|> _update_acl()
|
||||||
|> broadcast_acl_updates(map_id)
|
|> _broadcast_acl_updates()
|
||||||
|
|
||||||
state
|
|
||||||
else
|
|
||||||
state
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event(:cleanup_connections, %{map_id: map_id} = state) do
|
def handle_event(:cleanup_connections, %{map_id: map_id} = state) do
|
||||||
@@ -751,7 +679,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
} ->
|
} ->
|
||||||
DateTime.diff(DateTime.utc_now(), inserted_at, :hour) >=
|
DateTime.diff(DateTime.utc_now(), inserted_at, :hour) >=
|
||||||
@connection_auto_eol_hours and
|
@connection_auto_eol_hours and
|
||||||
is_connection_valid(
|
_is_connection_valid(
|
||||||
:wormholes,
|
:wormholes,
|
||||||
solar_system_source_id,
|
solar_system_source_id,
|
||||||
solar_system_target_id
|
solar_system_target_id
|
||||||
@@ -779,7 +707,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
solar_system_source: solar_system_source_id,
|
solar_system_source: solar_system_source_id,
|
||||||
solar_system_target: solar_system_target_id
|
solar_system_target: solar_system_target_id
|
||||||
} ->
|
} ->
|
||||||
connection_mark_eol_time = get_connection_mark_eol_time(map_id, connection_id)
|
connection_mark_eol_time = _get_connection_mark_eol_time(map_id, connection_id)
|
||||||
|
|
||||||
reverse_connection =
|
reverse_connection =
|
||||||
WandererApp.Map.get_connection(
|
WandererApp.Map.get_connection(
|
||||||
@@ -789,23 +717,24 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
)
|
)
|
||||||
|
|
||||||
is_connection_exist =
|
is_connection_exist =
|
||||||
is_connection_exist(
|
_is_connection_exist(
|
||||||
map_id,
|
map_id,
|
||||||
solar_system_source_id,
|
solar_system_source_id,
|
||||||
solar_system_target_id
|
solar_system_target_id
|
||||||
) || not is_nil(reverse_connection)
|
)
|
||||||
|
|
||||||
is_connection_valid =
|
is_connection_valid =
|
||||||
is_connection_valid(
|
_is_connection_valid(
|
||||||
:wormholes,
|
:wormholes,
|
||||||
solar_system_source_id,
|
solar_system_source_id,
|
||||||
solar_system_target_id
|
solar_system_target_id
|
||||||
)
|
)
|
||||||
|
|
||||||
not is_connection_exist ||
|
not is_connection_exist or
|
||||||
(is_connection_valid &&
|
not is_nil(reverse_connection) or
|
||||||
|
(is_connection_valid and
|
||||||
(DateTime.diff(DateTime.utc_now(), inserted_at, :hour) >=
|
(DateTime.diff(DateTime.utc_now(), inserted_at, :hour) >=
|
||||||
@connection_auto_expire_hours ||
|
@connection_auto_expire_hours or
|
||||||
DateTime.diff(DateTime.utc_now(), connection_mark_eol_time, :hour) >=
|
DateTime.diff(DateTime.utc_now(), connection_mark_eol_time, :hour) >=
|
||||||
@connection_auto_expire_hours - @connection_auto_eol_hours))
|
@connection_auto_expire_hours - @connection_auto_eol_hours))
|
||||||
end)
|
end)
|
||||||
@@ -824,76 +753,6 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event(:cleanup_characters, %{map_id: map_id, map: %{owner_id: owner_id}} = state) do
|
|
||||||
Process.send_after(self(), :cleanup_characters, @characters_cleanup_timeout)
|
|
||||||
|
|
||||||
{:ok, character_ids} =
|
|
||||||
WandererApp.Cache.lookup(
|
|
||||||
"map_#{map_id}:invalidate_character_ids",
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
|
|
||||||
character_ids
|
|
||||||
|> Task.async_stream(
|
|
||||||
fn character_id ->
|
|
||||||
character_id
|
|
||||||
|> WandererApp.Character.get_character()
|
|
||||||
|> case do
|
|
||||||
{:ok, character} ->
|
|
||||||
acls =
|
|
||||||
map_id
|
|
||||||
|> WandererApp.Map.get_map!()
|
|
||||||
|> Map.get(:acls, [])
|
|
||||||
|
|
||||||
[character_permissions] =
|
|
||||||
WandererApp.Permissions.check_characters_access([character], acls)
|
|
||||||
|
|
||||||
map_permissions =
|
|
||||||
WandererApp.Permissions.get_map_permissions(
|
|
||||||
character_permissions,
|
|
||||||
owner_id,
|
|
||||||
[character_id]
|
|
||||||
)
|
|
||||||
|
|
||||||
case map_permissions do
|
|
||||||
%{view_system: false} ->
|
|
||||||
{:remove_character, character_id}
|
|
||||||
|
|
||||||
%{track_character: false} ->
|
|
||||||
{:remove_character, character_id}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
timeout: :timer.seconds(60),
|
|
||||||
max_concurrency: System.schedulers_online(),
|
|
||||||
on_timeout: :kill_task
|
|
||||||
)
|
|
||||||
|> Enum.each(fn
|
|
||||||
{:ok, {:remove_character, character_id}} ->
|
|
||||||
state |> remove_and_untrack_characters([character_id])
|
|
||||||
:ok
|
|
||||||
|
|
||||||
{:ok, _result} ->
|
|
||||||
:ok
|
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
@logger.error("Error in cleanup_characters: #{inspect(reason)}")
|
|
||||||
end)
|
|
||||||
|
|
||||||
WandererApp.Cache.insert(
|
|
||||||
"map_#{map_id}:invalidate_character_ids",
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
|
|
||||||
state
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event(:cleanup_systems, %{map_id: map_id} = state) do
|
def handle_event(:cleanup_systems, %{map_id: map_id} = state) do
|
||||||
Process.send_after(self(), :cleanup_systems, @systems_cleanup_timeout)
|
Process.send_after(self(), :cleanup_systems, @systems_cleanup_timeout)
|
||||||
|
|
||||||
@@ -953,9 +812,8 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
do: %{
|
do: %{
|
||||||
state
|
state
|
||||||
| map_opts: [
|
| map_opts: [
|
||||||
layout: options |> Map.get("layout", "left_to_right"),
|
layout: options |> Map.get("layout"),
|
||||||
store_custom_labels:
|
store_custom_labels: options |> Map.get("store_custom_labels")
|
||||||
options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom()
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,62 +830,41 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def broadcast!(map_id, event, payload \\ nil) do
|
def broadcast!(map_id, event, payload \\ nil) do
|
||||||
if can_broadcast?(map_id) do
|
if _can_broadcast?(map_id) do
|
||||||
@pubsub_client.broadcast!(WandererApp.PubSub, map_id, %{event: event, payload: payload})
|
@pubsub_client.broadcast!(WandererApp.PubSub, map_id, %{event: event, payload: payload})
|
||||||
end
|
end
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
defp remove_and_untrack_characters(%{map_id: map_id} = state, character_ids) do
|
defp _get_connection_mark_eol_time(map_id, connection_id) do
|
||||||
map_id
|
case WandererApp.Cache.get("map_#{map_id}:conn_#{connection_id}:mark_eol_time") do
|
||||||
|> _untrack_characters(character_ids)
|
|
||||||
|
|
||||||
case WandererApp.Api.MapCharacterSettings.tracked_by_map(%{
|
|
||||||
map_id: map_id,
|
|
||||||
character_ids: character_ids
|
|
||||||
}) do
|
|
||||||
{:ok, settings} ->
|
|
||||||
settings
|
|
||||||
|> Enum.map(fn s ->
|
|
||||||
s |> WandererApp.Api.MapCharacterSettings.untrack()
|
|
||||||
state |> remove_character(s.character_id)
|
|
||||||
end)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_connection_mark_eol_time(map_id, connection_id, default \\ DateTime.utc_now()) do
|
|
||||||
WandererApp.Cache.get("map_#{map_id}:conn_#{connection_id}:mark_eol_time")
|
|
||||||
|> case do
|
|
||||||
nil ->
|
nil ->
|
||||||
default
|
DateTime.utc_now()
|
||||||
|
|
||||||
value ->
|
value ->
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp can_broadcast?(map_id),
|
defp _can_broadcast?(map_id),
|
||||||
do:
|
do:
|
||||||
not WandererApp.Cache.lookup!("map_#{map_id}:importing", false) and
|
not WandererApp.Cache.lookup!("map_#{map_id}:importing", false) and
|
||||||
WandererApp.Cache.lookup!("map_#{map_id}:started", false)
|
WandererApp.Cache.lookup!("map_#{map_id}:started", false)
|
||||||
|
|
||||||
defp update_location(
|
defp _update_location(
|
||||||
character_id,
|
character_id,
|
||||||
location,
|
location,
|
||||||
old_location,
|
old_location,
|
||||||
%{map: map, map_id: map_id, rtree_name: rtree_name, map_opts: map_opts} = _state
|
%{map: map, map_id: map_id, rtree_name: rtree_name, map_opts: map_opts} = _state
|
||||||
) do
|
) do
|
||||||
case is_nil(old_location.solar_system_id) and
|
case is_nil(old_location.solar_system_id) and
|
||||||
can_add_location(map.scope, location.solar_system_id) do
|
_can_add_location(map.scope, location.solar_system_id) do
|
||||||
true ->
|
true ->
|
||||||
:ok = maybe_add_system(map_id, location, nil, rtree_name, map_opts)
|
:ok = maybe_add_system(map_id, location, nil, rtree_name, map_opts)
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
case is_connection_valid(
|
case _is_connection_valid(
|
||||||
map.scope,
|
map.scope,
|
||||||
old_location.solar_system_id,
|
old_location.solar_system_id,
|
||||||
location.solar_system_id
|
location.solar_system_id
|
||||||
@@ -1043,7 +880,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_update_location(map_id, character_id) do
|
defp _maybe_update_location(map_id, character_id) do
|
||||||
WandererApp.Cache.lookup!(
|
WandererApp.Cache.lookup!(
|
||||||
"character:#{character_id}:location_started",
|
"character:#{character_id}:location_started",
|
||||||
false
|
false
|
||||||
@@ -1094,7 +931,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_update_alliance(map_id, character_id) do
|
defp _maybe_update_alliance(map_id, character_id) do
|
||||||
with {:ok, old_alliance_id} <-
|
with {:ok, old_alliance_id} <-
|
||||||
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:alliance_id"),
|
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:alliance_id"),
|
||||||
{:ok, %{alliance_id: alliance_id}} <-
|
{:ok, %{alliance_id: alliance_id}} <-
|
||||||
@@ -1118,7 +955,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_update_corporation(map_id, character_id) do
|
defp _maybe_update_corporation(map_id, character_id) do
|
||||||
with {:ok, old_corporation_id} <-
|
with {:ok, old_corporation_id} <-
|
||||||
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:corporation_id"),
|
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:corporation_id"),
|
||||||
{:ok, %{corporation_id: corporation_id}} <-
|
{:ok, %{corporation_id: corporation_id}} <-
|
||||||
@@ -1142,7 +979,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_update_online(map_id, character_id) do
|
defp _maybe_update_online(map_id, character_id) do
|
||||||
with {:ok, old_online} <-
|
with {:ok, old_online} <-
|
||||||
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:online"),
|
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:online"),
|
||||||
{:ok, %{online: online}} <-
|
{:ok, %{online: online}} <-
|
||||||
@@ -1166,7 +1003,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_update_ship(map_id, character_id) do
|
defp _maybe_update_ship(map_id, character_id) do
|
||||||
with {:ok, old_ship_type_id} <-
|
with {:ok, old_ship_type_id} <-
|
||||||
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:ship_type_id"),
|
WandererApp.Cache.lookup("map:#{map_id}:character:#{character_id}:ship_type_id"),
|
||||||
{:ok, old_ship_name} <-
|
{:ok, old_ship_name} <-
|
||||||
@@ -1198,7 +1035,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp update_connection(
|
defp _update_connection(
|
||||||
%{map_id: map_id} = state,
|
%{map_id: map_id} = state,
|
||||||
update_method,
|
update_method,
|
||||||
attributes,
|
attributes,
|
||||||
@@ -1214,7 +1051,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
solar_system_source_id,
|
solar_system_source_id,
|
||||||
solar_system_target_id
|
solar_system_target_id
|
||||||
),
|
),
|
||||||
{:ok, update_map} <- get_update_map(update, attributes),
|
{:ok, update_map} <- _get_update_map(update, attributes),
|
||||||
:ok <-
|
:ok <-
|
||||||
WandererApp.Map.update_connection(
|
WandererApp.Map.update_connection(
|
||||||
map_id,
|
map_id,
|
||||||
@@ -1240,7 +1077,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp update_system(
|
defp _update_system(
|
||||||
%{map_id: map_id} = state,
|
%{map_id: map_id} = state,
|
||||||
update_method,
|
update_method,
|
||||||
attributes,
|
attributes,
|
||||||
@@ -1253,7 +1090,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
map_id,
|
map_id,
|
||||||
update.solar_system_id
|
update.solar_system_id
|
||||||
),
|
),
|
||||||
{:ok, update_map} <- get_update_map(update, attributes) do
|
{:ok, update_map} <- _get_update_map(update, attributes) do
|
||||||
{:ok, updated_system} =
|
{:ok, updated_system} =
|
||||||
apply(WandererApp.MapSystemRepo, update_method, [
|
apply(WandererApp.MapSystemRepo, update_method, [
|
||||||
system,
|
system,
|
||||||
@@ -1264,7 +1101,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
callback_fn.(updated_system)
|
callback_fn.(updated_system)
|
||||||
end
|
end
|
||||||
|
|
||||||
update_map_system_last_activity(map_id, updated_system)
|
_update_map_system_last_activity(map_id, updated_system)
|
||||||
|
|
||||||
state
|
state
|
||||||
else
|
else
|
||||||
@@ -1274,7 +1111,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_update_map(update, attributes),
|
defp _get_update_map(update, attributes),
|
||||||
do:
|
do:
|
||||||
{:ok,
|
{:ok,
|
||||||
Enum.reduce(attributes, Map.new(), fn attribute, map ->
|
Enum.reduce(attributes, Map.new(), fn attribute, map ->
|
||||||
@@ -1318,8 +1155,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
rtree_name
|
rtree_name
|
||||||
)
|
)
|
||||||
|
|
||||||
existing_system
|
{:ok, existing_system}
|
||||||
|> WandererApp.MapSystemRepo.update_visible(%{visible: true})
|
|
||||||
else
|
else
|
||||||
@ddrt.insert(
|
@ddrt.insert(
|
||||||
{solar_system_id,
|
{solar_system_id,
|
||||||
@@ -1333,8 +1169,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
existing_system
|
existing_system
|
||||||
|> WandererApp.MapSystemRepo.update_position!(%{position_x: x, position_y: y})
|
|> WandererApp.MapSystemRepo.update_position!(%{position_x: x, position_y: y})
|
||||||
|> WandererApp.MapSystemRepo.cleanup_labels!(map_opts)
|
|> WandererApp.MapSystemRepo.cleanup_labels!(map_opts)
|
||||||
|> WandererApp.MapSystemRepo.cleanup_tags!()
|
|> WandererApp.MapSystemRepo.cleanup_tags()
|
||||||
|> WandererApp.MapSystemRepo.update_visible(%{visible: true})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
@@ -1380,7 +1215,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
defp save_map_state(%{map_id: map_id} = _state) do
|
defp _save_map_state(%{map_id: map_id} = _state) do
|
||||||
systems_last_activity =
|
systems_last_activity =
|
||||||
map_id
|
map_id
|
||||||
|> WandererApp.Map.list_systems!()
|
|> WandererApp.Map.list_systems!()
|
||||||
@@ -1414,7 +1249,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_stop_rtree(%{rtree_name: rtree_name} = state) do
|
defp _maybe_stop_rtree(%{rtree_name: rtree_name} = state) do
|
||||||
case Process.whereis(rtree_name) do
|
case Process.whereis(rtree_name) do
|
||||||
nil ->
|
nil ->
|
||||||
:ok
|
:ok
|
||||||
@@ -1426,7 +1261,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
defp init_map_cache(%__MODULE__{map_id: map_id} = state) do
|
defp _init_map_cache(%__MODULE__{map_id: map_id} = state) do
|
||||||
case WandererApp.Api.MapState.by_map_id(map_id) do
|
case WandererApp.Api.MapState.by_map_id(map_id) do
|
||||||
{:ok,
|
{:ok,
|
||||||
%{
|
%{
|
||||||
@@ -1458,9 +1293,9 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp init_map(
|
defp _init_map(
|
||||||
state,
|
state,
|
||||||
%{id: map_id, characters: characters} = initial_map,
|
%{characters: characters} = initial_map,
|
||||||
subscription_settings,
|
subscription_settings,
|
||||||
systems,
|
systems,
|
||||||
connections
|
connections
|
||||||
@@ -1476,24 +1311,16 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
{:ok, map_options} = WandererApp.MapRepo.options_to_form_data(initial_map)
|
{:ok, map_options} = WandererApp.MapRepo.options_to_form_data(initial_map)
|
||||||
|
|
||||||
map_opts = [
|
map_opts = [
|
||||||
layout: map_options |> Map.get("layout", "left_to_right"),
|
layout: map_options |> Map.get("layout"),
|
||||||
store_custom_labels:
|
store_custom_labels: map_options |> Map.get("store_custom_labels")
|
||||||
map_options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom()
|
|
||||||
]
|
]
|
||||||
|
|
||||||
character_ids =
|
|
||||||
map_id
|
|
||||||
|> WandererApp.Map.get_map!()
|
|
||||||
|> Map.get(:characters, [])
|
|
||||||
|
|
||||||
WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids)
|
|
||||||
|
|
||||||
%{state | map: map, map_opts: map_opts}
|
%{state | map: map, map_opts: map_opts}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp init_map_systems(state, [] = _systems), do: state
|
defp _init_map_systems(state, [] = _systems), do: state
|
||||||
|
|
||||||
defp init_map_systems(%__MODULE__{map_id: map_id, rtree_name: rtree_name} = state, systems) do
|
defp _init_map_systems(%__MODULE__{map_id: map_id, rtree_name: rtree_name} = state, systems) do
|
||||||
systems
|
systems
|
||||||
|> Enum.each(fn %{id: system_id, solar_system_id: solar_system_id} = system ->
|
|> Enum.each(fn %{id: system_id, solar_system_id: solar_system_id} = system ->
|
||||||
@ddrt.insert(
|
@ddrt.insert(
|
||||||
@@ -1511,7 +1338,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_import_systems(state, %{"systems" => systems} = _settings, user_id, character_id) do
|
def _maybe_import_systems(state, %{"systems" => systems} = _settings, user_id, character_id) do
|
||||||
state =
|
state =
|
||||||
systems
|
systems
|
||||||
|> Enum.reduce(state, fn %{
|
|> Enum.reduce(state, fn %{
|
||||||
@@ -1555,7 +1382,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
|> delete_systems(removed_system_ids, user_id, character_id)
|
|> delete_systems(removed_system_ids, user_id, character_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_import_connections(state, %{"connections" => connections} = _settings, _user_id) do
|
def _maybe_import_connections(state, %{"connections" => connections} = _settings, _user_id) do
|
||||||
connections
|
connections
|
||||||
|> Enum.reduce(state, fn %{
|
|> Enum.reduce(state, fn %{
|
||||||
"source" => source,
|
"source" => source,
|
||||||
@@ -1591,7 +1418,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_import_hubs(state, %{"hubs" => hubs} = _settings, _user_id) do
|
def _maybe_import_hubs(state, %{"hubs" => hubs} = _settings, _user_id) do
|
||||||
hubs
|
hubs
|
||||||
|> Enum.reduce(state, fn hub, acc ->
|
|> Enum.reduce(state, fn hub, acc ->
|
||||||
solar_system_id = hub |> String.to_integer()
|
solar_system_id = hub |> String.to_integer()
|
||||||
@@ -1601,7 +1428,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp update_map_system_last_activity(
|
defp _update_map_system_last_activity(
|
||||||
map_id,
|
map_id,
|
||||||
updated_system
|
updated_system
|
||||||
) do
|
) do
|
||||||
@@ -1614,13 +1441,13 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
broadcast!(map_id, :update_system, updated_system)
|
broadcast!(map_id, :update_system, updated_system)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp can_add_location(_scope, nil), do: false
|
defp _can_add_location(_scope, nil), do: false
|
||||||
|
|
||||||
defp can_add_location(:all, _solar_system_id), do: true
|
defp _can_add_location(:all, _solar_system_id), do: true
|
||||||
|
|
||||||
defp can_add_location(:none, _solar_system_id), do: false
|
defp _can_add_location(:none, _solar_system_id), do: false
|
||||||
|
|
||||||
defp can_add_location(scope, solar_system_id) do
|
defp _can_add_location(scope, solar_system_id) do
|
||||||
system_static_info =
|
system_static_info =
|
||||||
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
|
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
|
||||||
{:ok, system_static_info} when not is_nil(system_static_info) ->
|
{:ok, system_static_info} when not is_nil(system_static_info) ->
|
||||||
@@ -1645,14 +1472,14 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp is_connection_exist(map_id, from_solar_system_id, to_solar_system_id),
|
defp _is_connection_exist(map_id, from_solar_system_id, to_solar_system_id),
|
||||||
do:
|
do:
|
||||||
not is_nil(
|
not is_nil(
|
||||||
WandererApp.Map.find_system_by_location(
|
WandererApp.Map.find_system_by_location(
|
||||||
map_id,
|
map_id,
|
||||||
%{solar_system_id: from_solar_system_id}
|
%{solar_system_id: from_solar_system_id}
|
||||||
)
|
)
|
||||||
) &&
|
) and
|
||||||
not is_nil(
|
not is_nil(
|
||||||
WandererApp.Map.find_system_by_location(
|
WandererApp.Map.find_system_by_location(
|
||||||
map_id,
|
map_id,
|
||||||
@@ -1660,13 +1487,13 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
defp is_connection_valid(_scope, nil, _to_solar_system_id), do: false
|
defp _is_connection_valid(_scope, nil, _to_solar_system_id), do: false
|
||||||
|
|
||||||
defp is_connection_valid(:all, _from_solar_system_id, _to_solar_system_id), do: true
|
defp _is_connection_valid(:all, _from_solar_system_id, _to_solar_system_id), do: true
|
||||||
|
|
||||||
defp is_connection_valid(:none, _from_solar_system_id, _to_solar_system_id), do: false
|
defp _is_connection_valid(:none, _from_solar_system_id, _to_solar_system_id), do: false
|
||||||
|
|
||||||
defp is_connection_valid(scope, from_solar_system_id, to_solar_system_id) do
|
defp _is_connection_valid(scope, from_solar_system_id, to_solar_system_id) do
|
||||||
{:ok, known_jumps} =
|
{:ok, known_jumps} =
|
||||||
WandererApp.Api.MapSolarSystemJumps.find(%{
|
WandererApp.Api.MapSolarSystemJumps.find(%{
|
||||||
before_system_id: from_solar_system_id,
|
before_system_id: from_solar_system_id,
|
||||||
@@ -1695,7 +1522,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp update_presence(map_id) do
|
defp _update_presence(map_id) do
|
||||||
case WandererApp.Cache.lookup!("map_#{map_id}:started", false) and
|
case WandererApp.Cache.lookup!("map_#{map_id}:started", false) and
|
||||||
WandererApp.Cache.get_and_remove!("map_#{map_id}:presence_updated", false) do
|
WandererApp.Cache.get_and_remove!("map_#{map_id}:presence_updated", false) do
|
||||||
true ->
|
true ->
|
||||||
@@ -1713,7 +1540,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
not Enum.member?(presence_character_ids, character_id)
|
not Enum.member?(presence_character_ids, character_id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
track_characters(presence_character_ids, map_id)
|
_track_characters(presence_character_ids, map_id)
|
||||||
|
|
||||||
map_id
|
map_id
|
||||||
|> _untrack_characters(not_present_character_ids)
|
|> _untrack_characters(not_present_character_ids)
|
||||||
@@ -1732,32 +1559,34 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp track_acls([]), do: :ok
|
defp _track_acls([]), do: :ok
|
||||||
|
|
||||||
defp track_acls([acl_id | rest]) do
|
defp _track_acls([acl_id | rest]) do
|
||||||
track_acl(acl_id)
|
_track_acl(acl_id)
|
||||||
track_acls(rest)
|
_track_acls(rest)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp track_acl(acl_id),
|
defp _track_acl(acl_id),
|
||||||
do: @pubsub_client.subscribe(WandererApp.PubSub, "acls:#{acl_id}")
|
|
||||||
|
|
||||||
defp track_characters([], _map_id), do: :ok
|
|
||||||
|
|
||||||
defp track_characters([character_id | rest], map_id) do
|
|
||||||
track_character(character_id, map_id)
|
|
||||||
track_characters(rest, map_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp track_character(character_id, map_id),
|
|
||||||
do:
|
do:
|
||||||
WandererApp.Character.TrackerManager.update_track_settings(character_id, %{
|
WandererApp.PubSub
|
||||||
map_id: map_id,
|
|> @pubsub_client.subscribe("acls:#{acl_id}")
|
||||||
track: true,
|
|
||||||
track_online: true,
|
defp _track_characters([], _map_id), do: :ok
|
||||||
track_location: true,
|
|
||||||
track_ship: true
|
defp _track_characters([character_id | rest], map_id) do
|
||||||
})
|
_track_character(character_id, map_id)
|
||||||
|
_track_characters(rest, map_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp _track_character(character_id, map_id) do
|
||||||
|
WandererApp.Character.TrackerManager.update_track_settings(character_id, %{
|
||||||
|
map_id: map_id,
|
||||||
|
track: true,
|
||||||
|
track_online: true,
|
||||||
|
track_location: true,
|
||||||
|
track_ship: true
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
defp _update_character(map_id, character_id) do
|
defp _update_character(map_id, character_id) do
|
||||||
{:ok, character} = WandererApp.Character.get_character(character_id)
|
{:ok, character} = WandererApp.Character.get_character(character_id)
|
||||||
@@ -1919,14 +1748,12 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
broadcast!(map_id, :add_system, new_system)
|
broadcast!(map_id, :add_system, new_system)
|
||||||
WandererApp.Map.add_system(map_id, new_system)
|
WandererApp.Map.add_system(map_id, new_system)
|
||||||
|
|
||||||
error ->
|
_ ->
|
||||||
@logger.debug("Failed to create system: #{inspect(error, pretty: true)}")
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
error ->
|
{:error, _} ->
|
||||||
@logger.debug("Skip adding system: #{inspect(error, pretty: true)}")
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1940,14 +1767,13 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
|> WandererApp.Map.find_system_by_location(old_location)
|
|> WandererApp.Map.find_system_by_location(old_location)
|
||||||
|> WandererApp.Map.PositionCalculator.get_new_system_position(rtree_name, opts)}
|
|> WandererApp.Map.PositionCalculator.get_new_system_position(rtree_name, opts)}
|
||||||
|
|
||||||
defp broadcast_acl_updates(
|
defp _broadcast_acl_updates(
|
||||||
{:ok,
|
{:ok,
|
||||||
%{
|
%{
|
||||||
eve_character_ids: eve_character_ids,
|
eve_character_ids: eve_character_ids,
|
||||||
eve_corporation_ids: eve_corporation_ids,
|
eve_corporation_ids: eve_corporation_ids,
|
||||||
eve_alliance_ids: eve_alliance_ids
|
eve_alliance_ids: eve_alliance_ids
|
||||||
}},
|
}}
|
||||||
map_id
|
|
||||||
) do
|
) do
|
||||||
eve_character_ids
|
eve_character_ids
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
@@ -1979,19 +1805,12 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
character_ids =
|
|
||||||
map_id
|
|
||||||
|> WandererApp.Map.get_map!()
|
|
||||||
|> Map.get(:characters, [])
|
|
||||||
|
|
||||||
WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids)
|
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
defp broadcast_acl_updates(_, _map_id), do: :ok
|
defp _broadcast_acl_updates(_), do: :ok
|
||||||
|
|
||||||
defp update_acl(acl_id) do
|
defp _update_acl(acl_id) do
|
||||||
{:ok, %{owner: owner, members: members}} =
|
{:ok, %{owner: owner, members: members}} =
|
||||||
WandererApp.AccessListRepo.get(acl_id, [:owner, :members])
|
WandererApp.AccessListRepo.get(acl_id, [:owner, :members])
|
||||||
|
|
||||||
|
|||||||
@@ -87,113 +87,4 @@ defmodule WandererApp.Permissions do
|
|||||||
delete_map: check_permission(user_permissions, @delete_map)
|
delete_map: check_permission(user_permissions, @delete_map)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_characters_access(characters, acls) do
|
|
||||||
character_ids = characters |> Enum.map(& &1.id)
|
|
||||||
character_eve_ids = characters |> Enum.map(& &1.eve_id)
|
|
||||||
|
|
||||||
character_corporation_ids =
|
|
||||||
characters |> Enum.map(& &1.corporation_id) |> Enum.map(&to_string/1)
|
|
||||||
|
|
||||||
character_alliance_ids = characters |> Enum.map(& &1.alliance_id) |> Enum.map(&to_string/1)
|
|
||||||
|
|
||||||
result =
|
|
||||||
acls
|
|
||||||
|> Enum.reduce([0, 0], fn acl, acc ->
|
|
||||||
is_owner? = acl.owner_id in character_ids
|
|
||||||
|
|
||||||
is_character_member? =
|
|
||||||
acl.members |> Enum.any?(fn member -> member.eve_character_id in character_eve_ids end)
|
|
||||||
|
|
||||||
is_corporation_member? =
|
|
||||||
acl.members
|
|
||||||
|> Enum.any?(fn member -> member.eve_corporation_id in character_corporation_ids end)
|
|
||||||
|
|
||||||
is_alliance_member? =
|
|
||||||
acl.members
|
|
||||||
|> Enum.any?(fn member -> member.eve_alliance_id in character_alliance_ids end)
|
|
||||||
|
|
||||||
if is_owner? || is_character_member? || is_corporation_member? || is_alliance_member? do
|
|
||||||
case acc do
|
|
||||||
[_, -1] ->
|
|
||||||
[-1, -1]
|
|
||||||
|
|
||||||
[-1, char_acc] ->
|
|
||||||
char_acl_mask =
|
|
||||||
acl.members
|
|
||||||
|> Enum.filter(fn member ->
|
|
||||||
member.eve_character_id in character_eve_ids
|
|
||||||
end)
|
|
||||||
|> Enum.reduce(0, fn member, acc ->
|
|
||||||
case acc do
|
|
||||||
-1 -> -1
|
|
||||||
_ -> calc_role_mask(member.role, acc)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
char_acc =
|
|
||||||
case char_acl_mask do
|
|
||||||
-1 -> -1
|
|
||||||
_ -> char_acc ||| char_acl_mask
|
|
||||||
end
|
|
||||||
|
|
||||||
[-1, char_acc]
|
|
||||||
|
|
||||||
[any_acc, char_acc] ->
|
|
||||||
any_acl_mask =
|
|
||||||
acl.members
|
|
||||||
|> Enum.filter(fn member ->
|
|
||||||
member.eve_character_id in character_eve_ids ||
|
|
||||||
member.eve_corporation_id in character_corporation_ids ||
|
|
||||||
member.eve_alliance_id in character_alliance_ids
|
|
||||||
end)
|
|
||||||
|> Enum.reduce(0, fn member, acc ->
|
|
||||||
case acc do
|
|
||||||
-1 -> -1
|
|
||||||
_ -> calc_role_mask(member.role, acc)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
char_acl_mask =
|
|
||||||
acl.members
|
|
||||||
|> Enum.filter(fn member ->
|
|
||||||
member.eve_character_id in character_eve_ids
|
|
||||||
end)
|
|
||||||
|> Enum.reduce(0, fn member, acc ->
|
|
||||||
case acc do
|
|
||||||
-1 -> -1
|
|
||||||
_ -> calc_role_mask(member.role, acc)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
any_acc =
|
|
||||||
case any_acl_mask do
|
|
||||||
-1 -> -1
|
|
||||||
_ -> any_acc ||| any_acl_mask
|
|
||||||
end
|
|
||||||
|
|
||||||
char_acc =
|
|
||||||
case char_acl_mask do
|
|
||||||
-1 -> -1
|
|
||||||
_ -> char_acc ||| char_acl_mask
|
|
||||||
end
|
|
||||||
|
|
||||||
[any_acc, char_acc]
|
|
||||||
end
|
|
||||||
else
|
|
||||||
acc
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
case result do
|
|
||||||
[_, -1] ->
|
|
||||||
[-1]
|
|
||||||
|
|
||||||
[-1, char_acc] ->
|
|
||||||
[char_acc]
|
|
||||||
|
|
||||||
[any_acc, _char_acc] ->
|
|
||||||
[any_acc]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ defmodule WandererApp.MapSystemRepo do
|
|||||||
|
|
||||||
def cleanup_labels!(%{labels: labels} = system, opts) do
|
def cleanup_labels!(%{labels: labels} = system, opts) do
|
||||||
store_custom_labels? =
|
store_custom_labels? =
|
||||||
Keyword.get(opts, :store_custom_labels)
|
Keyword.get(opts, :store_custom_labels, "false") |> String.to_existing_atom()
|
||||||
|
|
||||||
labels = get_filtered_labels(labels, store_custom_labels?)
|
labels = get_filtered_labels(labels, store_custom_labels?)
|
||||||
|
|
||||||
system
|
system
|
||||||
|> update_labels!(%{
|
|> WandererApp.Api.MapSystem.update_labels!(%{
|
||||||
labels: labels
|
labels: labels
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@@ -52,13 +52,6 @@ defmodule WandererApp.MapSystemRepo do
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def cleanup_tags!(system) do
|
|
||||||
system
|
|
||||||
|> WandererApp.Api.MapSystem.update_tag!(%{
|
|
||||||
tag: nil
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_filtered_labels(labels, true) when is_binary(labels) do
|
def get_filtered_labels(labels, true) when is_binary(labels) do
|
||||||
labels
|
labels
|
||||||
|> Jason.decode!()
|
|> Jason.decode!()
|
||||||
@@ -104,11 +97,6 @@ defmodule WandererApp.MapSystemRepo do
|
|||||||
system
|
system
|
||||||
|> WandererApp.Api.MapSystem.update_labels(update)
|
|> WandererApp.Api.MapSystem.update_labels(update)
|
||||||
|
|
||||||
def update_labels!(system, update),
|
|
||||||
do:
|
|
||||||
system
|
|
||||||
|> WandererApp.Api.MapSystem.update_labels!(update)
|
|
||||||
|
|
||||||
def update_position(system, update),
|
def update_position(system, update),
|
||||||
do:
|
do:
|
||||||
system
|
system
|
||||||
@@ -118,14 +106,4 @@ defmodule WandererApp.MapSystemRepo do
|
|||||||
do:
|
do:
|
||||||
system
|
system
|
||||||
|> WandererApp.Api.MapSystem.update_position!(update)
|
|> WandererApp.Api.MapSystem.update_position!(update)
|
||||||
|
|
||||||
def update_visible(system, update),
|
|
||||||
do:
|
|
||||||
system
|
|
||||||
|> WandererApp.Api.MapSystem.update_visible(update)
|
|
||||||
|
|
||||||
def update_visible!(system, update),
|
|
||||||
do:
|
|
||||||
system
|
|
||||||
|> WandererApp.Api.MapSystem.update_visible!(update)
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
defmodule WandererAppWeb.AccessListsLive do
|
defmodule WandererAppWeb.AccessListsLive do
|
||||||
alias Pathex.Builder.Viewer
|
|
||||||
use WandererAppWeb, :live_view
|
use WandererAppWeb, :live_view
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
@@ -90,10 +89,7 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
|> assign(:page_title, "Access Lists - Members")
|
|> assign(:page_title, "Access Lists - Members")
|
||||||
|> assign(:selected_acl_id, acl_id)
|
|> assign(:selected_acl_id, acl_id)
|
||||||
|> assign(:access_list, access_list)
|
|> assign(:access_list, access_list)
|
||||||
|> assign(
|
|> assign(:members, members)
|
||||||
:members,
|
|
||||||
members
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
socket
|
socket
|
||||||
@@ -149,7 +145,7 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
:send_after,
|
:send_after,
|
||||||
[self(), {:search, text}, 100],
|
[self(), {:search, text}, 100],
|
||||||
"member_search_#{socket.assigns.selected_acl_id}",
|
"member_search_#{socket.assigns.selected_acl_id}",
|
||||||
250
|
500
|
||||||
)
|
)
|
||||||
|
|
||||||
[%{label: "Loading...", value: :loading, disabled: true}]
|
[%{label: "Loading...", value: :loading, disabled: true}]
|
||||||
@@ -292,11 +288,7 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event(
|
def handle_event("dropped", %{"draggedId" => dragged_id, "dropzoneId" => dropzone_id}, socket) do
|
||||||
"dropped",
|
|
||||||
%{"draggedId" => dragged_id, "dropzoneId" => dropzone_id},
|
|
||||||
%{assigns: %{access_list: access_list, members: members}} = socket
|
|
||||||
) do
|
|
||||||
role_atom =
|
role_atom =
|
||||||
[:admin, :manager, :member, :viewer, :blocked]
|
[:admin, :manager, :member, :viewer, :blocked]
|
||||||
|> Enum.find(fn role_atom -> to_string(role_atom) == dropzone_id end)
|
|> Enum.find(fn role_atom -> to_string(role_atom) == dropzone_id end)
|
||||||
@@ -307,27 +299,13 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
|
|
||||||
role_atom ->
|
role_atom ->
|
||||||
member =
|
member =
|
||||||
members
|
socket.assigns.members
|
||||||
|> Enum.find(&(&1.id == dragged_id))
|
|> Enum.find(&(&1.id == dragged_id))
|
||||||
|
|
||||||
{:noreply, socket |> maybe_update_role(member, role_atom, access_list)}
|
{:noreply, socket |> maybe_update_role(member, role_atom, socket.assigns.access_list)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_info(
|
|
||||||
{"update_role", %{member_id: member_id, role: role}},
|
|
||||||
%{assigns: %{access_list: access_list, members: members}} = socket
|
|
||||||
) do
|
|
||||||
role_atom = role |> String.to_existing_atom()
|
|
||||||
|
|
||||||
member =
|
|
||||||
members
|
|
||||||
|> Enum.find(&(&1.id == member_id))
|
|
||||||
|
|
||||||
{:noreply, socket |> maybe_update_role(member, role_atom, access_list)}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_event("noop", _, socket) do
|
def handle_event("noop", _, socket) do
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
@@ -347,33 +325,10 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
|> Enum.map(& &1.id)
|
|> Enum.map(& &1.id)
|
||||||
|> Enum.at(0)
|
|> Enum.at(0)
|
||||||
|
|
||||||
uniq_search_req_id = UUID.uuid4(:default)
|
{:ok, options} = search(active_character_id, text)
|
||||||
|
|
||||||
Task.async(fn ->
|
send_update(LiveSelect.Component, options: options, id: socket.assigns.member_search_id)
|
||||||
{:ok, options} = search(active_character_id, text)
|
{:noreply, socket |> assign(member_search_options: options)}
|
||||||
|
|
||||||
{:search_results, uniq_search_req_id, options}
|
|
||||||
end)
|
|
||||||
|
|
||||||
{:noreply, socket |> assign(uniq_search_req_id: uniq_search_req_id)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_info(
|
|
||||||
{ref, result},
|
|
||||||
%{assigns: %{member_search_id: member_search_id, uniq_search_req_id: uniq_search_req_id}} =
|
|
||||||
socket
|
|
||||||
)
|
|
||||||
when is_reference(ref) do
|
|
||||||
Process.demonitor(ref, [:flush])
|
|
||||||
|
|
||||||
case result do
|
|
||||||
{:search_results, ^uniq_search_req_id, options} ->
|
|
||||||
send_update(LiveSelect.Component, options: options, id: member_search_id)
|
|
||||||
{:noreply, socket |> assign(member_search_options: options)}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:noreply, socket}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -448,7 +403,6 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
_ ->
|
_ ->
|
||||||
socket
|
socket
|
||||||
|> put_flash(:error, "You're not allowed to assign this role")
|
|> put_flash(:error, "You're not allowed to assign this role")
|
||||||
|> push_navigate(to: ~p"/access-lists/#{socket.assigns.selected_acl_id}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -457,11 +411,10 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
_member,
|
_member,
|
||||||
_role_atom,
|
_role_atom,
|
||||||
_access_list
|
_access_list
|
||||||
),
|
) do
|
||||||
do:
|
socket
|
||||||
socket
|
|> put_flash(:info, "Only Characters can have Admin or Manager roles")
|
||||||
|> put_flash(:info, "Only Characters can have Admin or Manager roles")
|
end
|
||||||
|> push_navigate(to: ~p"/access-lists/#{socket.assigns.selected_acl_id}")
|
|
||||||
|
|
||||||
defp characters_has_role?(character_eve_ids, access_list, role_atom) do
|
defp characters_has_role?(character_eve_ids, access_list, role_atom) do
|
||||||
access_list.members
|
access_list.members
|
||||||
@@ -661,6 +614,27 @@ defmodule WandererAppWeb.AccessListsLive do
|
|||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def member_item(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<.icon :if={not is_nil(@member.role)} name={member_role_icon(@member.role)} class="w-6 h-6" />
|
||||||
|
<div class="avatar">
|
||||||
|
<div class="rounded-md w-8 h-8">
|
||||||
|
<img src={member_icon_url(@member)} alt={@member.name} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= @member.name %>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
def member_role_icon(:admin), do: "hero-user-group-solid"
|
||||||
|
def member_role_icon(:manager), do: "hero-academic-cap-solid"
|
||||||
|
def member_role_icon(:member), do: "hero-user-solid"
|
||||||
|
def member_role_icon(:viewer), do: "hero-eye-solid"
|
||||||
|
def member_role_icon(:blocked), do: "hero-no-symbol-solid text-red-500"
|
||||||
|
def member_role_icon(_), do: "hero-cake-solid"
|
||||||
|
|
||||||
def search_member_icon_url(%{character: true} = option),
|
def search_member_icon_url(%{character: true} = option),
|
||||||
do: member_icon_url(%{eve_character_id: option.value})
|
do: member_icon_url(%{eve_character_id: option.value})
|
||||||
|
|
||||||
|
|||||||
@@ -82,20 +82,14 @@
|
|||||||
id="acl_members"
|
id="acl_members"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:for={member <- @members |> Enum.sort_by(&{&1.role, &1.name}, &<=/2)}
|
:for={member <- @members |> Enum.sort(&(&1.name < &2.name))}
|
||||||
draggable="true"
|
draggable="true"
|
||||||
id={member.id}
|
id={member.id}
|
||||||
class="draggable !p-1 h-10 cursor-move bg-black bg-opacity-25 hover:text-white"
|
class="draggable !p-1 h-10 cursor-move bg-black bg-opacity-25 hover:text-white"
|
||||||
data-dropzone="pool"
|
data-dropzone="pool"
|
||||||
>
|
>
|
||||||
<div class="flex justify-between relative">
|
<div class="flex justify-between relative">
|
||||||
<.live_component
|
<.member_item member={member} />
|
||||||
module={WandererAppWeb.AclMember}
|
|
||||||
id={"select_role_" <> member.id}
|
|
||||||
notify_to={self()}
|
|
||||||
member={member}
|
|
||||||
event_name="update_role"
|
|
||||||
/>
|
|
||||||
<button
|
<button
|
||||||
:if={can_delete_member?(member, @access_list, @current_user)}
|
:if={can_delete_member?(member, @access_list, @current_user)}
|
||||||
class="z-10 absolute top-0 right-2"
|
class="z-10 absolute top-0 right-2"
|
||||||
@@ -156,71 +150,6 @@
|
|||||||
show
|
show
|
||||||
on_cancel={JS.patch(~p"/access-lists/#{@selected_acl_id}")}
|
on_cancel={JS.patch(~p"/access-lists/#{@selected_acl_id}")}
|
||||||
>
|
>
|
||||||
<%!-- <div class="mt-4 mb-2 p-tabmenu p-component " data-pc-section="tabmenu">
|
|
||||||
<ul
|
|
||||||
class="p-tabmenu-nav border-none h-[25px] w-full flex"
|
|
||||||
role="menubar"
|
|
||||||
data-pc-section="menu"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
id="pr_id_17_0"
|
|
||||||
class="p-tabmenuitem p-highlight"
|
|
||||||
role="presentation"
|
|
||||||
data-p-highlight="true"
|
|
||||||
data-p-disabled="false"
|
|
||||||
data-pc-section="menuitem"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
role="menuitem"
|
|
||||||
aria-label="Router Link"
|
|
||||||
tabindex="0"
|
|
||||||
class="p-menuitem-link"
|
|
||||||
data-pc-section="action"
|
|
||||||
>
|
|
||||||
<span class="p-menuitem-text" data-pc-section="label">Character</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
id="pr_id_17_1"
|
|
||||||
class="p-tabmenuitem"
|
|
||||||
role="presentation"
|
|
||||||
data-p-highlight="false"
|
|
||||||
data-p-disabled="false"
|
|
||||||
data-pc-section="menuitem"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
role="menuitem"
|
|
||||||
aria-label="Programmatic"
|
|
||||||
tabindex="-1"
|
|
||||||
class="p-menuitem-link"
|
|
||||||
data-pc-section="action"
|
|
||||||
>
|
|
||||||
<span class="p-menuitem-text" data-pc-section="label">Corporation</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
id="pr_id_17_2"
|
|
||||||
class="p-tabmenuitem"
|
|
||||||
role="presentation"
|
|
||||||
data-p-highlight="false"
|
|
||||||
data-p-disabled="false"
|
|
||||||
data-pc-section="menuitem"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
role="menuitem"
|
|
||||||
aria-label="External"
|
|
||||||
tabindex="-1"
|
|
||||||
class="p-menuitem-link"
|
|
||||||
data-pc-section="action"
|
|
||||||
>
|
|
||||||
<span class="p-menuitem-text" data-pc-section="label">Alliance</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div> --%>
|
|
||||||
<.form :let={f} for={@member_form} phx-submit={@live_action}>
|
<.form :let={f} for={@member_form} phx-submit={@live_action}>
|
||||||
<.live_select
|
<.live_select
|
||||||
field={f[:member_id]}
|
field={f[:member_id]}
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
defmodule WandererAppWeb.AclMember do
|
|
||||||
use WandererAppWeb, :live_component
|
|
||||||
|
|
||||||
use LiveViewEvents
|
|
||||||
|
|
||||||
@roles [
|
|
||||||
:admin,
|
|
||||||
:manager,
|
|
||||||
:member,
|
|
||||||
:viewer,
|
|
||||||
:blocked
|
|
||||||
]
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def mount(socket) do
|
|
||||||
{:ok, socket |> assign(roles: get_roles())}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def update(
|
|
||||||
%{
|
|
||||||
member: member
|
|
||||||
} = assigns,
|
|
||||||
socket
|
|
||||||
) do
|
|
||||||
socket = handle_info_or_assign(socket, assigns)
|
|
||||||
|
|
||||||
{:ok,
|
|
||||||
socket
|
|
||||||
|> assign(member: member, form: to_form(%{"role" => member.role}))}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def render(assigns) do
|
|
||||||
~H"""
|
|
||||||
<div id={@id} class="flex items-center gap-2">
|
|
||||||
<.icon :if={not is_nil(@member.role)} name={member_role_icon(@member.role)} class="w-6 h-6" />
|
|
||||||
<.form :let={f} id={"role_form_" <> @id} for={@form} phx-change="select" phx-target={@myself}>
|
|
||||||
<.input
|
|
||||||
type="select"
|
|
||||||
field={f[:role]}
|
|
||||||
class="select h-8 min-h-[0px] !pt-1 !pb-1 text-sm bg-neutral-900 w-[70px]"
|
|
||||||
placeholder="Select a role..."
|
|
||||||
options={Enum.map(@roles, fn role -> {role.label, role.value} end)}
|
|
||||||
/>
|
|
||||||
</.form>
|
|
||||||
<div class="avatar">
|
|
||||||
<div class="rounded-md w-8 h-8">
|
|
||||||
<img src={member_icon_url(@member)} alt={@member.name} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<%= @member.name %>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_event(
|
|
||||||
"select",
|
|
||||||
%{"role" => role} = _params,
|
|
||||||
%{assigns: %{event_name: event_name, member: member, notify_to: notify_to}} = socket
|
|
||||||
) do
|
|
||||||
notify_to(notify_to, event_name, %{
|
|
||||||
member_id: member.id,
|
|
||||||
role: role
|
|
||||||
})
|
|
||||||
|
|
||||||
{:noreply, socket}
|
|
||||||
end
|
|
||||||
|
|
||||||
def member_role_icon(:admin), do: "hero-user-group-solid"
|
|
||||||
def member_role_icon(:manager), do: "hero-academic-cap-solid"
|
|
||||||
def member_role_icon(:member), do: "hero-user-solid"
|
|
||||||
def member_role_icon(:viewer), do: "hero-eye-solid"
|
|
||||||
def member_role_icon(:blocked), do: "hero-no-symbol-solid text-red-500"
|
|
||||||
def member_role_icon(_), do: "hero-cake-solid"
|
|
||||||
|
|
||||||
def member_role_title(:admin), do: "Admin"
|
|
||||||
def member_role_title(:manager), do: "Manager"
|
|
||||||
def member_role_title(:member), do: "Member"
|
|
||||||
def member_role_title(:viewer), do: "Viewer"
|
|
||||||
def member_role_title(:blocked), do: "-blocked-"
|
|
||||||
def member_role_title(_), do: "-"
|
|
||||||
|
|
||||||
defp get_roles(), do: @roles |> Enum.map(&%{label: member_role_title(&1), value: &1})
|
|
||||||
end
|
|
||||||
@@ -162,16 +162,6 @@ defmodule WandererAppWeb.MapConnectionsEventHandler do
|
|||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_ui_event(
|
|
||||||
"get_connection_info",
|
|
||||||
%{"from" => from, "to" => to} = _event,
|
|
||||||
%{assigns: %{map_id: map_id}} = socket
|
|
||||||
) do
|
|
||||||
{:ok, info} = map_id |> get_connection_info(from, to)
|
|
||||||
|
|
||||||
{:reply, info, socket}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_ui_event(
|
def handle_ui_event(
|
||||||
"get_passages",
|
"get_passages",
|
||||||
%{"from" => from, "to" => to} = _event,
|
%{"from" => from, "to" => to} = _event,
|
||||||
@@ -204,19 +194,4 @@ defmodule WandererAppWeb.MapConnectionsEventHandler do
|
|||||||
|
|
||||||
{:ok, %{passages: passages}}
|
{:ok, %{passages: passages}}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_connection_info(map_id, from, to) do
|
|
||||||
map_id
|
|
||||||
|> WandererApp.Map.Server.get_connection_info(%{
|
|
||||||
solar_system_source_id: "#{from}" |> String.to_integer(),
|
|
||||||
solar_system_target_id: "#{to}" |> String.to_integer()
|
|
||||||
})
|
|
||||||
|> case do
|
|
||||||
{:ok, info} ->
|
|
||||||
{:ok, info}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:ok, %{}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ defmodule WandererAppWeb.MapEventHandler do
|
|||||||
@map_connection_ui_events [
|
@map_connection_ui_events [
|
||||||
"manual_add_connection",
|
"manual_add_connection",
|
||||||
"manual_delete_connection",
|
"manual_delete_connection",
|
||||||
"get_connection_info",
|
|
||||||
"get_passages",
|
"get_passages",
|
||||||
"update_connection_time_status",
|
"update_connection_time_status",
|
||||||
"update_connection_mass_status",
|
"update_connection_mass_status",
|
||||||
@@ -154,7 +153,7 @@ defmodule WandererAppWeb.MapEventHandler do
|
|||||||
|
|
||||||
def handle_ui_event(event, body, socket)
|
def handle_ui_event(event, body, socket)
|
||||||
when event in @map_characters_ui_events,
|
when event in @map_characters_ui_events,
|
||||||
do: MapCharactersEventHandler.handle_ui_event(event, body, socket)
|
do: MapSystemsEventHandler.handle_ui_event(event, body, socket)
|
||||||
|
|
||||||
def handle_ui_event(event, body, socket)
|
def handle_ui_event(event, body, socket)
|
||||||
when event in @map_system_ui_events,
|
when event in @map_system_ui_events,
|
||||||
|
|||||||
2
mix.exs
2
mix.exs
@@ -2,7 +2,7 @@ defmodule WandererApp.MixProject do
|
|||||||
use Mix.Project
|
use Mix.Project
|
||||||
|
|
||||||
@source_url "https://github.com/wanderer-industries/wanderer"
|
@source_url "https://github.com/wanderer-industries/wanderer"
|
||||||
@version "1.15.0"
|
@version "1.13.7"
|
||||||
|
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
defmodule WandererApp.Repo.Migrations.InstallAshFunctionsExtension420240922090427 do
|
||||||
|
@moduledoc """
|
||||||
|
Installs any extensions that are mentioned in the repo's `installed_extensions/0` callback
|
||||||
|
|
||||||
|
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("""
|
||||||
|
CREATE OR REPLACE FUNCTION uuid_generate_v7()
|
||||||
|
RETURNS UUID
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
timestamp TIMESTAMPTZ;
|
||||||
|
microseconds INT;
|
||||||
|
BEGIN
|
||||||
|
timestamp = clock_timestamp();
|
||||||
|
microseconds = (cast(extract(microseconds FROM timestamp)::INT - (floor(extract(milliseconds FROM timestamp))::INT * 1000) AS DOUBLE PRECISION) * 4.096)::INT;
|
||||||
|
|
||||||
|
RETURN encode(
|
||||||
|
set_byte(
|
||||||
|
set_byte(
|
||||||
|
overlay(uuid_send(gen_random_uuid()) placing substring(int8send(floor(extract(epoch FROM timestamp) * 1000)::BIGINT) FROM 3) FROM 1 FOR 6
|
||||||
|
),
|
||||||
|
6, (b'0111' || (microseconds >> 8)::bit(4))::bit(8)::int
|
||||||
|
),
|
||||||
|
7, microseconds::bit(8)::int
|
||||||
|
),
|
||||||
|
'hex')::UUID;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
LANGUAGE PLPGSQL
|
||||||
|
VOLATILE;
|
||||||
|
""")
|
||||||
|
|
||||||
|
execute("""
|
||||||
|
CREATE OR REPLACE FUNCTION timestamp_from_uuid_v7(_uuid uuid)
|
||||||
|
RETURNS TIMESTAMP WITHOUT TIME ZONE
|
||||||
|
AS $$
|
||||||
|
SELECT to_timestamp(('x0000' || substr(_uuid::TEXT, 1, 8) || substr(_uuid::TEXT, 10, 4))::BIT(64)::BIGINT::NUMERIC / 1000);
|
||||||
|
$$
|
||||||
|
LANGUAGE SQL
|
||||||
|
IMMUTABLE PARALLEL SAFE STRICT;
|
||||||
|
""")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
# Uncomment this if you actually want to uninstall the extensions
|
||||||
|
# when this migration is rolled back:
|
||||||
|
execute("DROP FUNCTION IF EXISTS uuid_generate_v7(), timestamp_from_uuid_v7(uuid)")
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user