diff --git a/apps/shared/lib/gbfs_metadata.ex b/apps/shared/lib/gbfs_metadata.ex index b8697993fc..0a6adadd91 100644 --- a/apps/shared/lib/gbfs_metadata.ex +++ b/apps/shared/lib/gbfs_metadata.ex @@ -196,12 +196,10 @@ defmodule Transport.Shared.GBFSMetadata do defp localized_string?(_), do: false - def first_feed(%{"data" => data, "version" => version} = payload) do - # From GBFS 1.1 until GBFS 2.3 - if before_v3?(version) do + def first_feed(%{"data" => data} = payload) do + if before_v3?(payload) do first_language = payload |> languages() |> Enum.at(0) (data["en"] || data["fr"] || data[first_language])["feeds"] - # From GBFS 3.0 onwards else data["feeds"] end @@ -224,11 +222,9 @@ defmodule Transport.Shared.GBFSMetadata do end end - def languages(%{"data" => data, "version" => version} = payload) do - # From GBFS 1.1 until GBFS 2.3 - if before_v3?(version) do + def languages(%{"data" => data} = payload) do + if before_v3?(payload) do Map.keys(data) - # From GBFS 3.0 onwards else feed_url = payload |> first_feed() |> feed_url_by_name("system_information") @@ -242,7 +238,7 @@ defmodule Transport.Shared.GBFSMetadata do end @spec versions(map()) :: [binary()] | nil - defp versions(%{"data" => _data} = payload) do + def versions(%{"data" => _data} = payload) do versions_url = payload |> first_feed() |> feed_url_by_name("gbfs_versions") if is_nil(versions_url) do @@ -250,7 +246,7 @@ defmodule Transport.Shared.GBFSMetadata do else with {:ok, %{status_code: 200, body: body}} <- http_client().get(versions_url), {:ok, json} <- Jason.decode(body) do - json["data"]["versions"] |> Enum.map(fn json -> json["version"] end) |> Enum.sort(:desc) + json["data"]["versions"] |> Enum.map(& &1["version"]) |> Enum.sort(:desc) else _ -> nil end @@ -280,7 +276,10 @@ defmodule Transport.Shared.GBFSMetadata do payload |> first_feed() |> Enum.map(fn feed -> String.replace(feed["name"], ".json", "") end) end - defp before_v3?(version), do: String.starts_with?(version, ["1.", "2."]) + defp before_v3?(%{"version" => version}), do: String.starts_with?(version, ["1.", "2."]) + # No `version` key: GBFS 1.0 + # https://github.com/MobilityData/gbfs/blob/v1.1/gbfs.md#output-format + defp before_v3?(%{}), do: true defp http_client, do: Transport.Shared.Wrapper.HTTPoison.impl() end diff --git a/apps/shared/test/gbfs_metadata_test.exs b/apps/shared/test/gbfs_metadata_test.exs index da1cacd247..83d13ebe60 100644 --- a/apps/shared/test/gbfs_metadata_test.exs +++ b/apps/shared/test/gbfs_metadata_test.exs @@ -108,6 +108,118 @@ defmodule Transport.Shared.GBFSMetadataTest do end end + describe "versions" do + test "1.0 feed" do + json = + Jason.decode!(""" + { + "last_updated":1729501544, + "ttl":0, + "data":{ + "en":{ + "feeds":[ + { + "name":"system_information", + "url":"https://example.com/gbfs/system_information.json" + }, + { + "name":"station_information", + "url":"https://example.com/gbfs/station_information.json" + }, + { + "name":"station_status", + "url":"https://example.com/gbfs/station_status.json" + } + ] + } + } + } + """) + + assert ["1.0"] == versions(json) + end + + test "2.3 feed, no gbfs_versions feed" do + json = + Jason.decode!(""" + { + "last_updated":1729501544, + "ttl":0, + "version": "2.3", + "data":{ + "en":{ + "feeds":[ + { + "name":"system_information", + "url":"https://example.com/gbfs/system_information.json" + }, + { + "name":"station_information", + "url":"https://example.com/gbfs/station_information.json" + }, + { + "name":"station_status", + "url":"https://example.com/gbfs/station_status.json" + } + ] + } + } + } + """) + + assert ["2.3"] == versions(json) + end + + test "2.3 feed, gbfs_versions feed" do + gbfs_versions_url = "https://example.com/gbfs/gbfs_versions" + + setup_response( + gbfs_versions_url, + Jason.encode!(%{ + data: %{ + versions: [ + %{version: "2.3"}, + %{version: "3.0"} + ] + } + }) + ) + + json = + Jason.decode!(""" + { + "last_updated":1729501544, + "ttl":0, + "version": "2.3", + "data":{ + "en":{ + "feeds":[ + { + "name":"system_information", + "url":"https://example.com/gbfs/system_information.json" + }, + { + "name":"station_information", + "url":"https://example.com/gbfs/station_information.json" + }, + { + "name":"station_status", + "url":"https://example.com/gbfs/station_status.json" + }, + { + "name":"gbfs_versions", + "url":"#{gbfs_versions_url}" + } + ] + } + } + } + """) + + assert ["3.0", "2.3"] == versions(json) + end + end + describe "feeds" do test "3.0 feed" do json = diff --git a/apps/transport/lib/transport/gbfs_to_geojson.ex b/apps/transport/lib/transport/gbfs_to_geojson.ex index d8cd1be7ee..315e56cd34 100644 --- a/apps/transport/lib/transport/gbfs_to_geojson.ex +++ b/apps/transport/lib/transport/gbfs_to_geojson.ex @@ -97,7 +97,7 @@ defmodule Transport.GbfsToGeojson do # From GBFS 3.0 onwards defp station_name(%{"name" => names}) do - names |> hd() |> Map.get("name") + names |> hd() |> Map.get("text") end @spec add_station_status(map(), map()) :: map() diff --git a/apps/transport/test/transport/gbfs_to_geojson_test.exs b/apps/transport/test/transport/gbfs_to_geojson_test.exs index 10dbb36dd0..76d74bfdde 100644 --- a/apps/transport/test/transport/gbfs_to_geojson_test.exs +++ b/apps/transport/test/transport/gbfs_to_geojson_test.exs @@ -248,7 +248,7 @@ defmodule Transport.GbfsToGeojsonTest do |> Jason.decode!() |> get_in(["data", "stations"]) |> Enum.map(fn %{"name" => name} = payload -> - Map.put(payload, "name", [%{"language" => "fr", "name" => name}]) + Map.put(payload, "name", [%{"language" => "fr", "text" => name}]) end) %{"data" => %{"stations" => stations}} |> Jason.encode!()