towerops/lib/towerops_web/changelog_parser.ex
Graham McIntie 0fc36524b4 fix: resolve 500 errors on /activity and /changelog
- Activity feed: use schema modules instead of string table names in Ecto
  queries to fix UUID encoding (Postgrex expected binary, got string)
- Changelog parser: remove plain hyphen from separator character class
  to prevent splitting on date hyphens (2026-02-13)
2026-02-13 19:49:12 -06:00

46 lines
1.5 KiB
Elixir

defmodule ToweropsWeb.ChangelogParser do
@moduledoc "Parses priv/static/changelog.txt into structured entries."
@doc "Returns a list of %{date: Date.t(), title: String.t(), items: [String.t()]}"
def parse do
path = Application.app_dir(:towerops, "priv/static/changelog.txt")
case File.read(path) do
{:ok, content} -> parse_content(content)
{:error, _} -> []
end
end
defp parse_content(content) do
content
|> String.split("\n")
|> Enum.reduce([], fn line, acc ->
cond do
# Date header with title: "2026-02-13 — Title"
Regex.match?(~r/^\d{4}-\d{2}-\d{2}\s+[—–]\s+.+/, line) ->
[date_str | rest] = String.split(line, ~r/\s+[—–]\s+/, parts: 2)
title = List.first(rest, "")
entry = %{date: Date.from_iso8601!(String.trim(date_str)), title: String.trim(title), items: []}
[entry | acc]
# Date header without title: "2026-02-13"
Regex.match?(~r/^\d{4}-\d{2}-\d{2}\s*$/, line) ->
date = Date.from_iso8601!(String.trim(line))
entry = %{date: date, title: nil, items: []}
[entry | acc]
# Bullet point
String.starts_with?(String.trim(line), "* ") ->
add_item_to_current(acc, line |> String.trim() |> String.trim_leading("* "))
true ->
acc
end
end)
|> Enum.reverse()
end
defp add_item_to_current([current | rest], item), do: [%{current | items: current.items ++ [item]} | rest]
defp add_item_to_current([], _item), do: []
end