diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex index d133b563..83cef155 100644 --- a/lib/music_library/records.ex +++ b/lib/music_library/records.ex @@ -2,7 +2,7 @@ defmodule MusicLibrary.Records do import Ecto.Query, warn: false alias MusicLibrary.Repo - alias MusicLibrary.Records.Record + alias MusicLibrary.Records.{MusicBrainz, Record} def list_records(opts \\ []) do limit = Keyword.get(opts, :limit, 20) @@ -32,6 +32,61 @@ defmodule MusicLibrary.Records do Repo.one!(q) end + def import_from_musicbrainz(musicbrainz_id) do + with {:ok, release_group} <- MusicBrainz.get_release_group(musicbrainz_id), + {:ok, image_data} <- MusicBrainz.get_cover_art(musicbrainz_id), + record_params = build_record_params(release_group, image_data) do + create_record(record_params) + else + error -> error + end + end + + defp build_record_params(release_group, image_data) do + musicbrainz_id = release_group["id"] + + artists_attrs = + release_group + |> get_in(["artist-credit", Access.all(), "artist"]) + |> Enum.map(fn artist -> + %{ + name: artist["name"], + musicbrainz_id: artist["id"], + sort_name: artist["sort-name"], + disambiguation: artist["disambiguation"] + } + end) + + %{ + "musicbrainz_id" => musicbrainz_id, + "title" => release_group["title"], + "artists" => artists_attrs, + "year" => parse_year(release_group["first-release-date"]), + "type" => parse_subtype(release_group["primary-type"]), + "genres" => Enum.map(release_group["genres"], fn g -> g["name"] end), + "image_url" => "https://coverartarchive.org/release-group/#{musicbrainz_id}/front", + "image_data" => image_data + } + end + + defp parse_year(iso_date) when is_binary(iso_date) do + case Date.from_iso8601(iso_date) do + {:ok, date} -> + date.year + + _error -> + {year, _rest} = Integer.parse(iso_date) + {:ok, year} + end + end + + defp parse_subtype("Album"), do: :album + defp parse_subtype("EP"), do: :ep + defp parse_subtype("Live"), do: :live + defp parse_subtype("Compilation"), do: :compilation + defp parse_subtype("Single"), do: :single + defp parse_subtype(_), do: :other + def create_record(attrs \\ %{}) do %Record{} |> Record.changeset(attrs) diff --git a/lib/music_library_web/live/record_live/index.ex b/lib/music_library_web/live/record_live/index.ex index 104286d3..3b8a80e0 100644 --- a/lib/music_library_web/live/record_live/index.ex +++ b/lib/music_library_web/live/record_live/index.ex @@ -74,69 +74,28 @@ defmodule MusicLibraryWeb.RecordLive.Index do end def handle_event("import", %{"id" => musicbrainz_id}, socket) do - with {:ok, result} <- MusicLibrary.Records.MusicBrainz.get_release_group(musicbrainz_id), - {:ok, image_data} <- MusicLibrary.Records.MusicBrainz.get_cover_art(musicbrainz_id) do - artists_attrs = - result - |> get_in(["artist-credit", Access.all(), "artist"]) - |> Enum.map(fn artist -> - %{ - name: artist["name"], - musicbrainz_id: artist["id"], - sort_name: artist["sort-name"], - disambiguation: artist["disambiguation"] - } - end) + case Records.import_from_musicbrainz(musicbrainz_id) do + {:ok, record} -> + notify_parent({:saved, record}) - record_attrs = %{ - "musicbrainz_id" => musicbrainz_id, - "title" => result["title"], - "artists" => artists_attrs, - "year" => parse_year(result["first-release-date"]), - "type" => parse_subtype(result["primary-type"]), - "genres" => Enum.map(result["genres"], fn g -> g["name"] end), - "image_url" => "https://coverartarchive.org/release-group/#{musicbrainz_id}/front", - "image_data" => image_data - } + {:noreply, + socket + |> put_flash(:info, "Record imported successfully") + |> push_patch(to: ~p"/records")} - case Records.create_record(record_attrs) do - {:ok, record} -> - notify_parent({:saved, record}) + {:error, %Ecto.Changeset{} = changeset} -> + {:noreply, assign(socket, form: to_form(changeset))} - {:noreply, - socket - |> put_flash(:info, "Record imported successfully") - |> push_patch(to: ~p"/records")} - - {:error, %Ecto.Changeset{} = changeset} -> - {:noreply, assign(socket, form: to_form(changeset))} - end - else - {:error, _} -> - {:noreply, socket} + {:error, reason} -> + {:noreply, + socket + |> put_flash(:error, "Error importing record, #{inspect(reason)}") + |> push_patch(to: ~p"/records")} end end defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) - defp parse_year(iso_date) when is_binary(iso_date) do - case Date.from_iso8601(iso_date) do - {:ok, date} -> - date.year - - _error -> - {year, _rest} = Integer.parse(iso_date) - {:ok, year} - end - end - - defp parse_subtype("Album"), do: :album - defp parse_subtype("EP"), do: :ep - defp parse_subtype("Live"), do: :live - defp parse_subtype("Compilation"), do: :compilation - defp parse_subtype("Single"), do: :single - defp parse_subtype(_), do: :other - defp musicbrainz_url(record) do "https://musicbrainz.org/release-group/#{record.musicbrainz_id}" end