diff --git a/lib/music_brainz/api_behaviour.ex b/lib/music_brainz/api_behaviour.ex index 64a7738d..6ac0d1ab 100644 --- a/lib/music_brainz/api_behaviour.ex +++ b/lib/music_brainz/api_behaviour.ex @@ -1,10 +1,11 @@ defmodule MusicBrainz.APIBehaviour do @type musicbrainz_id :: String.t() @type config :: MusicBrainz.Config.t() + @type limit :: pos_integer() @callback get_release_group(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} - @callback get_releases(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} + @callback get_releases(musicbrainz_id, limit, config) :: {:ok, map()} | {:error, String.t()} @callback get_release(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} diff --git a/lib/music_brainz/api_impl.ex b/lib/music_brainz/api_impl.ex index 03ea5233..009f499c 100644 --- a/lib/music_brainz/api_impl.ex +++ b/lib/music_brainz/api_impl.ex @@ -7,6 +7,7 @@ defmodule MusicBrainz.APIImpl do """ @behaviour MusicBrainz.APIBehaviour + @base_url "https://musicbrainz.org/ws/2" require Logger @@ -288,9 +289,17 @@ defmodule MusicBrainz.APIImpl do end @impl true - def get_releases(release_group_id, config) do + def get_releases(release_group_id, opts, config) do + Keyword.validate!(opts, [:limit, :offset]) + + opts = + Keyword.merge(opts, + fmt: "json", + "release-group": release_group_id + ) + url = - "https://musicbrainz.org/ws/2/release?fmt=json&limit=100&release-group=#{release_group_id}" + @base_url <> "/release?" <> URI.encode_query(opts) json_get(url, config) end diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index 00477a11..e83714d0 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -226,14 +226,29 @@ defmodule MusicLibrary.Records do end end - # TODO: paginate and merge as needed defp merge_releases(musicbrainz_id, musicbrainz_data) do - with {:ok, data} <- - music_brainz_config().api.get_releases( - musicbrainz_id, - music_brainz_config() - ) do - {:ok, Map.put(musicbrainz_data, "releases", data["releases"])} + with {:ok, releases} <- stream_releases(musicbrainz_id) do + {:ok, Map.put(musicbrainz_data, "releases", releases)} + end + end + + defp stream_releases(musicbrainz_id) do + do_stream_releases(musicbrainz_id, [], 0) + end + + defp do_stream_releases(musicbrainz_id, releases, offset) do + limit = 100 + opts = [limit: limit, offset: offset] + + case music_brainz_config().api.get_releases(musicbrainz_id, opts, music_brainz_config()) do + {:ok, data} -> + %{"releases" => new_releases} = data + + if Enum.count(new_releases) < limit do + {:ok, releases ++ new_releases} + else + do_stream_releases(musicbrainz_id, releases ++ new_releases, offset + 100) + end end end diff --git a/test/music_library/records_test.exs b/test/music_library/records_test.exs index 9556ef05..e2f06d95 100644 --- a/test/music_library/records_test.exs +++ b/test/music_library/records_test.exs @@ -66,7 +66,7 @@ defmodule MusicLibrary.RecordsTest do {:ok, release_group(:lockdown_trilogy)} end) - expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config -> + expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config -> {:ok, %{"releases" => release_group(:lockdown_trilogy)["releases"]}} end) @@ -207,7 +207,7 @@ defmodule MusicLibrary.RecordsTest do {:ok, release_group} end) - expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config -> + expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config -> {:ok, %{"releases" => release_group["releases"]}} end) @@ -264,7 +264,7 @@ defmodule MusicLibrary.RecordsTest do {:ok, release_group} end) - expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config -> + expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config -> {:ok, %{"releases" => release_group["releases"]}} end) diff --git a/test/music_library_web/live/collection_live/index_test.exs b/test/music_library_web/live/collection_live/index_test.exs index 0fdf8bc5..0287d5f6 100644 --- a/test/music_library_web/live/collection_live/index_test.exs +++ b/test/music_library_web/live/collection_live/index_test.exs @@ -271,7 +271,7 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do {:ok, release_group} end) - expect(APIBehaviourMock, :get_releases, fn ^first_result_id, _config -> + expect(APIBehaviourMock, :get_releases, fn ^first_result_id, _opts, _config -> {:ok, %{"releases" => release_group["releases"]}} end) diff --git a/test/music_library_web/live/stats_live/index_test.exs b/test/music_library_web/live/stats_live/index_test.exs index 54417cc7..195287e8 100644 --- a/test/music_library_web/live/stats_live/index_test.exs +++ b/test/music_library_web/live/stats_live/index_test.exs @@ -193,7 +193,7 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do {:ok, release_group} end) - expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _config -> + expect(APIBehaviourMock, :get_releases, fn ^release_group_id, _opts, _config -> {:ok, %{"releases" => release_group["releases"]}} end)