Current section
Files
Jump to
Current section
Files
lib/server/slackdb_server.ex
defmodule SlackDB.Server do
@moduledoc false
use GenServer
alias SlackDB.Utils
alias SlackDB.Client
alias SlackDB.Utils
alias SlackDB.Messages
alias SlackDB.Channels
@required_keys [
:bot_token,
:user_token,
:bot_name,
:supervisor_channel_name,
:supervisor_channel_id
]
defp client(), do: Application.get_env(:slackdb, :client_adapter, Client)
defp slackdb(), do: Application.get_env(:slackdb, :slackdb_adapter, SlackDB)
defp messages(), do: Application.get_env(:slackdb, :messages_adapter, Messages)
defp channels(), do: Application.get_env(:slackdb, :channels_adapter, Channels)
@doc """
Start genserver, pull server config from application environment and pass to init/1
"""
def start_link do
config = Application.get_env(:slackdb, :servers)
GenServer.start_link(__MODULE__, config, name: __MODULE__)
end
####################################################################################
## GENSERVER CALLBACKS #############################################################
####################################################################################
@impl true
def init(config) do
case verify_config(config) do
{:error, msg} ->
{:stop, msg}
:ok ->
server_states =
config
|> Map.keys()
|> Enum.map(fn server_name ->
{server_name,
slackdb().read(
server_name,
get_in(config, [server_name, :supervisor_channel_name]),
server_name
)}
end)
|> Enum.map(&initialize_supervisor_channel/1)
config =
config
|> populate_channels(server_states)
{:ok, config}
end
end
@impl true
def handle_call(
{:create, server_name, channel_name, key_phrase, values, all_metadata},
_from,
state
) do
resp =
with channel_id when is_binary(channel_id) <-
get_in(state, [server_name, :channels, channel_name]) do
messages().post_key_val(server_name, channel_id, key_phrase, values, all_metadata)
else
nil -> {:error, "channel_name_not_in_database"}
end
{:reply, resp, state}
end
def handle_call({:invite, server_name, channel_name, user_ids}, _from, state)
when is_list(user_ids) do
resp =
with channel_id when is_binary(channel_id) <-
get_in(state, [server_name, :channels, channel_name]) do
channels().invite_to_channel(server_name, channel_id, user_ids)
else
nil -> {:error, "channel_name_not_in_database"}
end
{:reply, resp, state}
end
def handle_call({:put_channel, server_name, channel_name, channel_id}, _from, state) do
new_state = state |> put_in([server_name, :channels, channel_name], channel_id)
{:reply, {:ok, new_state}, new_state}
end
def handle_call({:archive, server_name, channel_name}, _from, state) do
resp =
with %{user_token: user_token, channels: channels} <- state[server_name] do
case channels[channel_name] do
nil ->
{:error, "channel_name_not_in_database"}
channel_id ->
client().conversations_archive(user_token, channel_id)
end
else
nil -> {:error, "server_not_found_in_config"}
%{} -> {:error, "improper_config"}
end
new_state =
case resp do
{:ok, _} ->
{_val, new} = state |> pop_in([server_name, :channels, channel_name])
new
{:error, _} ->
state
end
{:reply, resp, new_state}
end
def handle_call({:dump}, _from, state), do: {:reply, state, state}
####################################################################################
## INIT HELPERS ####################################################################
####################################################################################
defp populate_channels(map, []), do: map
defp populate_channels(map, [{server_name, state} | more_server_states]) do
populate_channels(map, more_server_states)
|> put_in([server_name, :channels], state)
end
defp initialize_supervisor_channel({server_name, {:ok, server_state}}) do
case server_state |> Jason.decode() do
{:ok, map} -> {server_name, map}
other -> {server_name, other}
end
end
defp initialize_supervisor_channel({server_name, {:error, _error_message}}) do
key_phrase = server_name
metadata = :single_back
init =
with [sprvsr_chnl_id] <- Utils.get_tokens(server_name, [:supervisor_channel_id]),
{:ok, _thread} <-
messages().post_key_val(server_name, sprvsr_chnl_id, key_phrase, "%{}", [metadata]) do
%{}
else
err -> err
end
{server_name, init}
end
defp verify_config(config) do
Enum.filter(config, fn
{_server_name, server_config} when is_map(server_config) ->
@required_keys
|> Enum.all?(&Map.has_key?(server_config, &1))
|> Kernel.not()
_ ->
true
end)
|> case do
[] ->
:ok
list ->
list_string = list |> Enum.map(&elem(&1, 0)) |> Enum.join(", ")
{:error, "The following servers are improperly configured: " <> list_string}
end
end
end