diff --git a/lib/last_fm/api_behaviour.ex b/lib/last_fm/api_behaviour.ex index e896db73..91e6213c 100644 --- a/lib/last_fm/api_behaviour.ex +++ b/lib/last_fm/api_behaviour.ex @@ -7,4 +7,6 @@ defmodule LastFm.APIBehaviour do @callback get_recent_tracks(config) :: {:ok, [Track.t()]} | {:error, String.t()} @callback get_artist_info({:musicbrainz_id, musicbrainz_id} | {:name, name}, config) :: {:ok, Artist.t()} | {:error, String.t()} + @callback get_similar_artists({:musicbrainz_id, musicbrainz_id} | {:name, name}, config) :: + {:ok, [Artist.t()]} | {:error, String.t()} end diff --git a/lib/last_fm/api_impl.ex b/lib/last_fm/api_impl.ex index 1e0c2c88..08f9f9d3 100644 --- a/lib/last_fm/api_impl.ex +++ b/lib/last_fm/api_impl.ex @@ -55,7 +55,7 @@ defmodule LastFm.APIImpl do do_get_artist_info([artist: artist_name], config) end - def do_get_artist_info(options, config) do + defp do_get_artist_info(options, config) do base_options = [ method: "artist.getInfo", api_key: config.api_key, @@ -86,6 +86,45 @@ defmodule LastFm.APIImpl do end end + @impl true + def get_similar_artists({:name, artist_name}, config) do + do_get_similar_artists([artist: artist_name], config) + end + + def get_similar_artists({:musicbrainz_id, artist_mbid}, config) do + do_get_similar_artists([mbid: artist_mbid], config) + end + + defp do_get_similar_artists(options, config) do + base_options = [ + method: "artist.getSimilar", + api_key: config.api_key, + format: "json", + limit: 50 + ] + + options = Keyword.merge(base_options, options) + + url = @base_url <> "?" <> URI.encode_query(options) + + Logger.debug("Fetching data from #{sanitize_url(url, config.api_key)}") + + case json_get(url, config.user_agent) do + {:ok, response} -> + {:ok, + response + |> get_in(["similarartists", "artist"]) + |> Enum.map(&Artist.from_api_response/1)} + + error -> + msg = + "Failed to fetch data from #{sanitize_url(url, config.api_key)}, reason: #{inspect(error)}" + + Logger.error(msg) + error + end + end + defp json_get(url, user_agent) do req = Finch.build(:get, url, [ diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index e9f4d6af..bfdacaad 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -136,6 +136,26 @@ defmodule MusicLibrary.Records do end end + def get_similar_artists(artist) do + last_fm_config = last_fm_config() + # Sometimes the artist info cannot be identified with the MusicBrainz ID, + # because Last.fm doesn't have that information. In that case, we try again with the artist name. + case last_fm_config.api.get_similar_artists( + {:musicbrainz_id, artist.musicbrainz_id}, + last_fm_config + ) do + {:ok, info} -> + {:ok, info} + + # TODO: remap error codes + {:error, %{"error" => 6}} -> + last_fm_config.api.get_similar_artists({:name, artist.name}, last_fm_config) + + error -> + error + end + end + def get_cover(id) do q = from r in Record,