2020-11-03 12:09:50 +03:00
|
|
|
defmodule PlausibleWeb.Tracker do
|
|
|
|
import Plug.Conn
|
2020-11-03 12:35:08 +03:00
|
|
|
use Agent
|
2020-11-03 12:20:11 +03:00
|
|
|
|
2021-07-23 15:17:32 +03:00
|
|
|
custom_script_name = Application.get_env(:plausible, :custom_script_name)
|
2021-08-13 15:13:25 +03:00
|
|
|
base_variants = ["hash", "outbound-links", "exclusions", "compat", "local"]
|
2021-07-23 15:17:32 +03:00
|
|
|
base_filenames = ["plausible", custom_script_name]
|
2021-05-18 11:36:12 +03:00
|
|
|
|
|
|
|
# Generates Power Set of all variants
|
|
|
|
variants =
|
|
|
|
1..Enum.count(base_variants)
|
|
|
|
|> Enum.map(fn x ->
|
|
|
|
Combination.combine(base_variants, x)
|
|
|
|
|> Enum.map(fn y -> Enum.sort(y) |> Enum.join(".") end)
|
|
|
|
end)
|
|
|
|
|> List.flatten()
|
|
|
|
|
|
|
|
# Formats power set into filenames
|
|
|
|
files_available =
|
|
|
|
["plausible.js", "p.js"] ++ Enum.map(variants, fn v -> "plausible.#{v}.js" end)
|
|
|
|
|
|
|
|
# Computes permutations for every power set elements, formats them as alias filenames
|
|
|
|
aliases_available =
|
|
|
|
Enum.map(variants, fn x ->
|
|
|
|
variants =
|
|
|
|
String.split(x, ".")
|
|
|
|
|> Combination.permutate()
|
|
|
|
|> Enum.map(fn p -> Enum.join(p, ".") end)
|
2021-07-23 15:17:32 +03:00
|
|
|
|> Enum.map(fn v -> Enum.map(base_filenames, fn filename -> "#{filename}.#{v}.js" end) end)
|
|
|
|
|> List.flatten()
|
2021-05-18 11:36:12 +03:00
|
|
|
|
|
|
|
if Enum.count(variants) > 0 do
|
|
|
|
{"plausible.#{x}.js", variants}
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|> Enum.reject(fn x -> x == nil end)
|
|
|
|
|> Enum.into(%{})
|
2021-07-23 15:17:32 +03:00
|
|
|
|> Map.put("plausible.js", ["analytics.js", "#{custom_script_name}.js"])
|
2021-05-18 11:36:12 +03:00
|
|
|
|
|
|
|
@templates files_available
|
|
|
|
@aliases aliases_available
|
2020-11-03 12:09:50 +03:00
|
|
|
|
|
|
|
def init(_) do
|
2021-05-18 15:24:45 +03:00
|
|
|
all_files =
|
|
|
|
Enum.reduce(@templates, %{}, fn template_filename, all_files ->
|
2020-11-03 12:20:11 +03:00
|
|
|
aliases = Map.get(@aliases, template_filename, [])
|
|
|
|
|
|
|
|
[template_filename | aliases]
|
2021-05-18 15:24:45 +03:00
|
|
|
|> Enum.map(fn filename -> {"/js/" <> filename, template_filename} end)
|
2020-11-03 12:20:11 +03:00
|
|
|
|> Enum.into(%{})
|
2021-05-18 15:24:45 +03:00
|
|
|
|> Map.merge(all_files)
|
2020-11-03 12:20:11 +03:00
|
|
|
end)
|
2020-11-03 12:09:50 +03:00
|
|
|
|
2021-05-18 15:24:45 +03:00
|
|
|
[files: all_files]
|
2020-11-03 12:09:50 +03:00
|
|
|
end
|
|
|
|
|
2021-05-18 15:24:45 +03:00
|
|
|
def call(conn, files: files) do
|
|
|
|
case files[conn.request_path] do
|
2020-12-29 16:17:27 +03:00
|
|
|
nil ->
|
|
|
|
conn
|
|
|
|
|
2020-11-03 12:35:08 +03:00
|
|
|
found ->
|
2021-05-18 15:24:45 +03:00
|
|
|
location = Application.app_dir(:plausible, "priv/tracker/js/" <> found)
|
2020-11-03 12:09:50 +03:00
|
|
|
|
2021-05-18 15:24:45 +03:00
|
|
|
conn
|
|
|
|
|> put_resp_header("content-type", "application/javascript")
|
2021-09-23 12:33:42 +03:00
|
|
|
|> put_resp_header("x-content-type-options", "nosniff")
|
2021-05-18 15:24:45 +03:00
|
|
|
|> put_resp_header("cross-origin-resource-policy", "cross-origin")
|
2021-06-29 15:33:13 +03:00
|
|
|
|> put_resp_header("access-control-allow-origin", "*")
|
2021-05-18 15:24:45 +03:00
|
|
|
|> send_file(200, location)
|
|
|
|
|> halt()
|
|
|
|
end
|
2020-11-03 12:09:50 +03:00
|
|
|
end
|
|
|
|
end
|