Current section
Files
Jump to
Current section
Files
lib/ua_inspector/database/clients.ex
defmodule UAInspector.Database.Clients do
@moduledoc false
use UAInspector.Storage.Server
require Logger
alias UAInspector.Config
alias UAInspector.Util
alias UAInspector.Util.YAML
@behaviour UAInspector.Storage.Database
@doc false
def start_link(init_arg) do
GenServer.start_link(__MODULE__, init_arg, name: __MODULE__)
end
@impl UAInspector.Storage.Database
def sources do
# files ordered according to
# https://github.com/matomo-org/device-detector/blob/master/DeviceDetector.php
# to prevent false detections
[
{"feed reader", "client.feed_readers.yml",
Config.database_url(:client, "feed_readers.yml")},
{"mobile app", "client.mobile_apps.yml", Config.database_url(:client, "mobile_apps.yml")},
{"mediaplayer", "client.mediaplayers.yml",
Config.database_url(:client, "mediaplayers.yml")},
{"pim", "client.pim.yml", Config.database_url(:client, "pim.yml")},
{"browser", "client.browsers.yml", Config.database_url(:client, "browsers.yml")},
{"library", "client.libraries.yml", Config.database_url(:client, "libraries.yml")}
]
end
defp parse_yaml_entries({:ok, entries}, _, type) do
Enum.map(entries, fn data ->
data = Enum.into(data, %{})
{
Util.build_regex(data["regex"]),
{
prepare_engine_data(type, data["engine"]),
YAML.maybe_to_string(data["name"]),
type,
YAML.maybe_to_string(data["version"])
}
}
end)
end
defp parse_yaml_entries({:error, error}, database, _) do
_ =
unless Config.get(:startup_silent) do
Logger.info("Failed to load database #{database}: #{inspect(error)}")
end
[]
end
defp prepare_engine_data("browser", [{"default", default}, {"versions", non_default}]) do
non_default =
non_default
|> Enum.map(fn {version, name} ->
{version |> to_string() |> Util.to_semver(), {name, Util.build_engine_regex(name)}}
end)
|> Enum.reverse()
[{"default", {default, Util.build_engine_regex(default)}}, {"versions", non_default}]
end
defp prepare_engine_data(_, [{"default", default}]) do
[{"default", {default, Util.build_engine_regex(default)}}]
end
defp prepare_engine_data(_, engine_data), do: engine_data
defp read_database do
sources()
|> Enum.reverse()
|> Enum.reduce([], fn {type, local, _remote}, acc ->
database = Path.join([Config.database_path(), local])
contents =
database
|> YAML.read_file()
|> parse_yaml_entries(database, type)
[contents | acc]
end)
|> List.flatten()
end
end