ML-153: move MusicBrainz data transforms from Record

This commit is contained in:
Claudio Ortolina
2026-04-30 13:19:25 +01:00
parent b8b3b24ffa
commit 13068aa0ac
3 changed files with 77 additions and 38 deletions
+51 -1
View File
@@ -1,5 +1,10 @@
defmodule MusicBrainz.ReleaseGroup do
@moduledoc false
@moduledoc """
Helper functions for working with MusicBrainz release group API responses.
Provides extraction and transformation utilities for release group data,
including artist credit parsing and type classification.
"""
alias MusicBrainz.ReleaseGroupSearchResult
@@ -45,6 +50,51 @@ defmodule MusicBrainz.ReleaseGroup do
def parse_type("Single"), do: :single
def parse_type(_), do: :other
@doc """
Parses artist credits from a MusicBrainz release group API response.
Extracts the `artist-credit` array and maps each artist into a map
suitable for use as an embedded artist in the application `Record` schema.
Returns a list of maps with keys: `:name`, `:musicbrainz_id`, `:sort_name`,
`:disambiguation`, and `:joinphrase`.
"""
@spec parse_artist_credits(map()) :: [map()]
def parse_artist_credits(musicbrainz_data) do
musicbrainz_data
|> get_in(["artist-credit", Access.all()])
|> Enum.map(fn artist_credit ->
%{
name: artist_credit["artist"]["name"],
musicbrainz_id: artist_credit["artist"]["id"],
sort_name: artist_credit["artist"]["sort-name"],
disambiguation: artist_credit["artist"]["disambiguation"],
joinphrase: artist_credit["joinphrase"]
}
end)
end
@doc """
Determines the application record type from MusicBrainz release group type fields.
Maps the `primary-type` and `secondary-types` fields from a MusicBrainz
release group API response to the application's record type enum values
(`:album`, `:ep`, `:live`, `:compilation`, `:single`, `:other`).
"""
@spec parse_record_type(String.t() | nil, [String.t()] | nil) :: atom()
def parse_record_type("Album", secondary_types) when is_list(secondary_types) do
cond do
"Live" in secondary_types -> :live
"Compilation" in secondary_types -> :compilation
true -> :album
end
end
def parse_record_type("Album", _secondary_types), do: :album
def parse_record_type("EP", _secondary_types), do: :ep
def parse_record_type("Single", _secondary_types), do: :single
def parse_record_type(_primary_type, _secondary_types), do: :other
defp get_release_groups(release_group) do
release_group
|> Map.get("relations", [])
+7 -31
View File
@@ -207,7 +207,7 @@ defmodule MusicLibrary.Records.Record do
changeset
musicbrainz_data ->
put_change(changeset, :artists, parse_artists(musicbrainz_data))
put_change(changeset, :artists, ReleaseGroup.parse_artist_credits(musicbrainz_data))
end
end
@@ -244,8 +244,7 @@ defmodule MusicLibrary.Records.Record do
@spec attrs_from_release_group(map()) :: map()
def attrs_from_release_group(release_group) do
musicbrainz_id = release_group["id"]
artists_attrs = parse_artists(release_group)
artists_attrs = ReleaseGroup.parse_artist_credits(release_group)
%{
"musicbrainz_id" => musicbrainz_id,
@@ -253,40 +252,17 @@ defmodule MusicLibrary.Records.Record do
"title" => release_group["title"],
"artists" => artists_attrs,
"release_date" => release_group["first-release-date"],
"type" => parse_subtype(release_group["primary-type"], release_group["secondary-types"]),
"type" =>
ReleaseGroup.parse_record_type(
release_group["primary-type"],
release_group["secondary-types"]
),
"genres" => Enum.map(release_group["genres"], fn g -> g["name"] end),
"release_ids" => Enum.map(release_group["releases"], fn r -> r["id"] end),
"cover_url" => "https://coverartarchive.org/release-group/#{musicbrainz_id}/front"
}
end
defp parse_artists(musicbrainz_data) do
musicbrainz_data
|> get_in(["artist-credit", Access.all()])
|> Enum.map(fn artist_credit ->
%{
name: artist_credit["artist"]["name"],
musicbrainz_id: artist_credit["artist"]["id"],
sort_name: artist_credit["artist"]["sort-name"],
disambiguation: artist_credit["artist"]["disambiguation"],
joinphrase: artist_credit["joinphrase"]
}
end)
end
defp parse_subtype("Album", secondary_types), do: parse_secondary_types(secondary_types)
defp parse_subtype("EP", _secondary_types), do: :ep
defp parse_subtype("Single", _secondary_types), do: :single
defp parse_subtype(_primary_type, _secondary_types), do: :other
defp parse_secondary_types(secondary_types) do
cond do
"Live" in secondary_types -> :live
"Compilation" in secondary_types -> :compilation
true -> :album
end
end
@doc """
Format a release date in a conventional format.