defmodule Mobilizon.Service.SiteMap do @moduledoc """ Generates a sitemap """ alias Mobilizon.{Actors, Events, Posts} alias Mobilizon.Storage.Repo alias Mobilizon.Web.Endpoint alias Mobilizon.Web.Router.Helpers, as: Routes @default_static_frequency :monthly @spec generate_sitemap :: {:ok, :ok} def generate_sitemap do static_routes = [ {Routes.page_url(Endpoint, :index, []), :daily}, "#{Endpoint.url()}/search", "#{Endpoint.url()}/about/instance", "#{Endpoint.url()}/terms", "#{Endpoint.url()}/privacy", "#{Endpoint.url()}/rules", "#{Endpoint.url()}/glossary" ] config = [ store: Sitemapper.FileStore, store_config: [path: Application.app_dir(:mobilizon, "priv/static")], sitemap_url: Endpoint.url(), gzip: false ] Repo.transaction( fn -> Events.stream_events_for_sitemap() |> Stream.concat(Actors.list_groups_for_stream()) |> Stream.concat(Posts.list_posts_for_stream()) |> Stream.concat( Enum.map(static_routes, fn route -> {url, frequency} = case route do {url, frequency} -> {url, frequency} url when is_binary(url) -> {url, @default_static_frequency} end %{url: url, updated_at: nil, frequence: frequency} end) ) |> Stream.map(fn %{url: url, updated_at: updated_at} = args -> frequence = Map.get(args, :frequence, :weekly) %Sitemapper.URL{ loc: url, changefreq: frequence, lastmod: check_date_time(updated_at) } end) |> Sitemapper.generate(config) |> Sitemapper.persist(config) |> Sitemapper.ping(config) |> Stream.run() end, timeout: :infinity ) end # Sometimes we use naive datetimes @spec check_date_time(any()) :: DateTime.t() | nil defp check_date_time(%NaiveDateTime{} = datetime), do: DateTime.from_naive!(datetime, "Etc/UTC") defp check_date_time(%DateTime{} = datetime), do: datetime defp check_date_time(_), do: nil end