diff --git a/lib/music_brainz/api_behaviour.ex b/lib/music_brainz/api_behaviour.ex index 90991f36..ca27fb46 100644 --- a/lib/music_brainz/api_behaviour.ex +++ b/lib/music_brainz/api_behaviour.ex @@ -1,12 +1,14 @@ defmodule MusicBrainz.APIBehaviour do @type musicbrainz_id :: String.t() + @type config :: MusicBrainz.Config.t() - @callback get_release_group(musicbrainz_id) :: {:ok, map()} | {:error, String.t()} + @callback get_release_group(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} - @callback get_release(musicbrainz_id) :: {:ok, map()} | {:error, String.t()} + @callback get_release(musicbrainz_id, config) :: {:ok, map()} | {:error, String.t()} - @callback search_release_group(String.t(), Keyword.t()) :: {:ok, [map()]} | {:error, String.t()} + @callback search_release_group(String.t(), Keyword.t(), config) :: + {:ok, [map()]} | {:error, String.t()} - @callback get_cover_art({:musicbrainz_id, musicbrainz_id()} | {:url, String.t()}) :: + @callback get_cover_art({:musicbrainz_id, musicbrainz_id()} | {:url, String.t()}, config) :: {:ok, binary()} | {:error, String.t()} end diff --git a/lib/music_brainz/api_impl.ex b/lib/music_brainz/api_impl.ex index f91799b7..c5366061 100644 --- a/lib/music_brainz/api_impl.ex +++ b/lib/music_brainz/api_impl.ex @@ -209,11 +209,11 @@ defmodule MusicBrainz.APIImpl do """ @impl true - def get_release_group(id) do + def get_release_group(id, config) do url = "https://musicbrainz.org/ws/2/release-group/#{id}?fmt=json&inc=artists+genres+releases+release-group-rels" - json_get(url) + json_get(url, config) end @doc """ @@ -280,11 +280,11 @@ defmodule MusicBrainz.APIImpl do } """ @impl true - def get_release(id) do + def get_release(id, config) do url = "https://musicbrainz.org/ws/2/release/#{id}?fmt=json&inc=release-groups" - json_get(url) + json_get(url, config) end @doc """ @@ -388,7 +388,7 @@ defmodule MusicBrainz.APIImpl do } """ @impl true - def search_release_group(query, opts) do + def search_release_group(query, opts, config) do limit = Keyword.fetch!(opts, :limit) offset = Keyword.fetch!(opts, :offset) @@ -402,7 +402,7 @@ defmodule MusicBrainz.APIImpl do url = "https://musicbrainz.org/ws/2/release-group?#{URI.encode_query(qs)}" - with {:ok, result} <- json_get(url) do + with {:ok, result} <- json_get(url, config) do {:ok, Enum.map(result["release-groups"], &ReleaseGroup.from_api_response/1)} end end @@ -411,14 +411,14 @@ defmodule MusicBrainz.APIImpl do Uses the [cover art](https://musicbrainz.org/doc/Cover_Art_Archive/API) endpoint with the release group id to get the cover image. """ @impl true - def get_cover_art({:musicbrainz_id, musicbrainz_id}) do + def get_cover_art({:musicbrainz_id, musicbrainz_id}, config) do url = "https://coverartarchive.org/release-group/#{musicbrainz_id}/front" - get_cover_art({:url, url}) + get_cover_art({:url, url}, config) end - def get_cover_art({:url, url}) do - case blob_get(url) do + def get_cover_art({:url, url}, config) do + case blob_get(url, config) do {:error, reason} -> Logger.error("Failed to fetch cover art for #{url}, reason: #{inspect(reason)}") @@ -429,10 +429,10 @@ defmodule MusicBrainz.APIImpl do end end - defp json_get(url) do + defp json_get(url, config) do req = Finch.build(:get, url, [ - {"User-Agent", "MusicLibrary/0.1.0 ( cloud8421@gmail.com )"} + {"User-Agent", config.user_agent} ]) Logger.debug("Fetching data from #{url}") @@ -444,7 +444,7 @@ defmodule MusicBrainz.APIImpl do {:ok, response} when response.status in 301..308 -> location = :proplists.get_value("location", response.headers) Logger.debug("Following redirect to #{location}") - json_get(location) + json_get(location, config) other -> msg = "Failed to fetch data from #{url}, reason: #{inspect(other)}" @@ -453,10 +453,10 @@ defmodule MusicBrainz.APIImpl do end end - defp blob_get(url) do + defp blob_get(url, config) do req = Finch.build(:get, url, [ - {"User-Agent", "MusicLibrary/0.1.0 ( cloud8421@gmail.com )"} + {"User-Agent", config.user_agent} ]) Logger.debug("Fetching data from #{url}") @@ -468,7 +468,7 @@ defmodule MusicBrainz.APIImpl do {:ok, response} when response.status in 301..308 -> location = :proplists.get_value("location", response.headers) Logger.debug("Following redirect to #{location}") - blob_get(location) + blob_get(location, config) # all non-success responses can be treated as errors {:ok, response} -> diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index 939fcc1a..febb6ae4 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -127,11 +127,16 @@ defmodule MusicLibrary.Records do def search_release_group(query, opts \\ []) do limit = Keyword.get(opts, :limit, 20) offset = Keyword.get(opts, :offset, 0) - music_brainz_config().api.search_release_group(query, limit: limit, offset: offset) + + music_brainz_config().api.search_release_group( + query, + [limit: limit, offset: offset], + music_brainz_config() + ) end def import_from_musicbrainz_release(musicbrainz_id, opts \\ []) do - case music_brainz_config().api.get_release(musicbrainz_id) do + case music_brainz_config().api.get_release(musicbrainz_id, music_brainz_config()) do {:ok, release} -> release_group_id = release["release-group"]["id"] import_from_musicbrainz_release_group(release_group_id, opts) @@ -144,7 +149,8 @@ defmodule MusicLibrary.Records do def import_from_musicbrainz_release_group(musicbrainz_id, opts \\ []) do with format = Keyword.get(opts, :format, "cd"), purchased_at = Keyword.get(opts, :purchased_at), - {:ok, release_group} <- music_brainz_config().api.get_release_group(musicbrainz_id), + {:ok, release_group} <- + music_brainz_config().api.get_release_group(musicbrainz_id, music_brainz_config()), {:ok, cover_data} <- get_cover_art_or_default(musicbrainz_id), record_attrs = build_record_attrs(release_group, %{ @@ -159,14 +165,21 @@ defmodule MusicLibrary.Records do end defp get_cover_art_or_default(musicbrainz_id) do - case music_brainz_config().api.get_cover_art({:musicbrainz_id, musicbrainz_id}) do + case music_brainz_config().api.get_cover_art( + {:musicbrainz_id, musicbrainz_id}, + music_brainz_config() + ) do {:error, :cover_not_available} -> {:ok, Record.fallback_cover_data()} {:ok, cover_data} -> Cover.resize(cover_data) end end def refresh_cover(record) do - with {:ok, cover_data} <- music_brainz_config().api.get_cover_art({:url, record.cover_url}) do + with {:ok, cover_data} <- + music_brainz_config().api.get_cover_art( + {:url, record.cover_url}, + music_brainz_config() + ) do {:ok, thumb_data} = Cover.resize(cover_data) record @@ -184,7 +197,11 @@ defmodule MusicLibrary.Records do end def refresh_musicbrainz_data(record) do - with {:ok, data} <- music_brainz_config().api.get_release_group(record.musicbrainz_id) do + with {:ok, data} <- + music_brainz_config().api.get_release_group( + record.musicbrainz_id, + music_brainz_config() + ) do record |> Record.add_musicbrainz_data(data) |> Repo.update() diff --git a/test/music_library/records_test.exs b/test/music_library/records_test.exs index bbca882f..b8802f8d 100644 --- a/test/music_library/records_test.exs +++ b/test/music_library/records_test.exs @@ -63,7 +63,7 @@ defmodule MusicLibrary.RecordsTest do assert record.release_ids == [] assert record.included_release_group_ids == [] - expect(APIBehaviourMock, :get_release_group, fn ^release_group_id -> + expect(APIBehaviourMock, :get_release_group, fn ^release_group_id, _config -> {:ok, release_group_with_includes()} end) @@ -193,7 +193,9 @@ defmodule MusicLibrary.RecordsTest do test "it returns results with correct limit and offset" do mock_results = release_group_search_results() - expect(APIBehaviourMock, :search_release_group, fn "Marillion", limit: 20, offset: 10 -> + expect(APIBehaviourMock, :search_release_group, fn "Marillion", + [limit: 20, offset: 10], + _config -> {:ok, mock_results} end) @@ -209,13 +211,13 @@ defmodule MusicLibrary.RecordsTest do release_group = release_group() release_group_id = release_group_id() - expect(APIBehaviourMock, :get_release_group, fn ^release_group_id -> + expect(APIBehaviourMock, :get_release_group, fn ^release_group_id, _config -> {:ok, release_group} end) cover_data = File.read!(marbles_cover_fixture()) - expect(APIBehaviourMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id} -> + expect(APIBehaviourMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id}, _config -> {:ok, cover_data} end) @@ -258,17 +260,17 @@ defmodule MusicLibrary.RecordsTest do release_group = release_group() release_group_id = release_group_id() - expect(APIBehaviourMock, :get_release, fn ^release_id -> + expect(APIBehaviourMock, :get_release, fn ^release_id, _config -> {:ok, release} end) - expect(APIBehaviourMock, :get_release_group, fn ^release_group_id -> + expect(APIBehaviourMock, :get_release_group, fn ^release_group_id, _config -> {:ok, release_group} end) cover_data = File.read!(marbles_cover_fixture()) - expect(APIBehaviourMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id} -> + expect(APIBehaviourMock, :get_cover_art, fn {:musicbrainz_id, ^release_group_id}, _config -> {:ok, cover_data} end) @@ -309,7 +311,7 @@ defmodule MusicLibrary.RecordsTest do cover_url = record.cover_url - expect(APIBehaviourMock, :get_cover_art, fn {:url, ^cover_url} -> + expect(APIBehaviourMock, :get_cover_art, fn {:url, ^cover_url}, _config -> {:ok, raven_cover_data} 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 dbe69e8c..b37a7ff8 100644 --- a/test/music_library_web/live/collection_live/index_test.exs +++ b/test/music_library_web/live/collection_live/index_test.exs @@ -275,8 +275,8 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do mock_results = release_group_search_results() expect(APIBehaviourMock, :search_release_group, fn "Marillion Marbles", - limit: 10, - offset: 0 -> + [limit: 10, offset: 0], + _config -> {:ok, mock_results} end) @@ -297,13 +297,13 @@ defmodule MusicLibraryWeb.CollectionLive.IndexTest do release_group = release_group() - expect(APIBehaviourMock, :get_release_group, fn ^first_result_id -> + expect(APIBehaviourMock, :get_release_group, fn ^first_result_id, _config -> {:ok, release_group} end) cover_data = File.read!(marbles_cover_fixture()) - expect(APIBehaviourMock, :get_cover_art, fn {:musicbrainz_id, ^first_result_id} -> + expect(APIBehaviourMock, :get_cover_art, fn {:musicbrainz_id, ^first_result_id}, _config -> {:ok, cover_data} end)